cap program drop ncreadtocsv program define ncreadtocsv syntax anything using/, csv(string) [Size(numlist integer) Origin(numlist integer >0) clear] local varname `anything' confirm name `varname' parsecsvopt `csv' local csvfile `r(file)' if `"`origin'"'!=""{ ncreadtocsvbysec `anything' using `using', csv(`csvfile') size(`size') origin(`origin') exit } removequotes,file(`"`using'"') local ncfile `r(file)' local no: word count `origin' if "`size'"==""{ forv j=1/`no'{ local size `size' -1 } } local nc: word count `size' if `nc' != `no' { di as error "The number of origin and size should be the same." exit } local ncfile = usubinstr(`"`ncfile'"',"\","/",.) local csvfile = usubinstr(`"`csvfile'"',"\","/",.) cap qui findfile NCtoCSV.java di //////////java////////////////////// // java clear // java: /cp "netcdfAll-5.6.0.jar" // java: /open "NCtoCSV.java" java: NCtoCSV.main("`ncfile'","`csvfile'","`varname'") end cap program drop parsecsvopt program define parsecsvopt,rclass syntax anything, [replace] local file `anything' local replace `replace' removequotes,file(`"`file'"') local file `r(file)' local flag = fileexists(`"`file'"') if "`replace'"=="" & `flag'{ di as error "file exist, adding replace in csv() to overwrite it." exit 198 } return local file `file' end /////////////////////////// cap program drop removequotes program define removequotes,rclass version 16 syntax, file(string) return local file `file' end cap program drop parsecsvopt program define parsecsvopt,rclass syntax anything, [replace] local file `anything' local replace `replace' removequotes,file(`"`file'"') local file `r(file)' local flag = fileexists(`"`file'"') if "`replace'"=="" & `flag'{ di as error "file exist, adding replace in csv() to overwrite it." exit 198 } return local file `file' end java: /cp netcdfAll-5.6.0.jar import ucar.nc2.dataset.NetcdfDataset; import ucar.nc2.Variable; import ucar.ma2.Array; import ucar.nc2.Dimension; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import ucar.ma2.InvalidRangeException; import com.stata.sfi.*; public class NCtoCSV { private static final int BUFFER_SIZE = 8192 * 1024; private static final long MAX_SAFE_ELEMENTS = 1_000_000_000; public static void main(String ncFilePath, String csvFilePath, String variableName) { try (NetcdfDataset ncDataset = NetcdfDataset.openDataset(ncFilePath)) { Variable mainVar = ncDataset.findVariable(variableName); if (mainVar == null) { SFIToolkit.errorln("Variable " + variableName + " not found"); return; } List<Variable> coordVars = new ArrayList<>(); Map<Variable, Integer> dimOrderMap = new HashMap<>(); List<Dimension> mainDims = mainVar.getDimensions(); for (int dimIndex = 0; dimIndex < mainDims.size(); dimIndex++) { Dimension dim = mainDims.get(dimIndex); Variable coordVar = ncDataset.findVariable(dim.getShortName()); if (coordVar != null) { coordVars.add(coordVar); dimOrderMap.put(coordVar, dimIndex); } } long totalSize = calculateTotalSize(coordVars); System.out.println("Total rows: " + totalSize); if (totalSize > MAX_SAFE_ELEMENTS) { SFIToolkit.errorln("Warning: Dataset too large"); return; } try (BufferedWriter writer = new BufferedWriter(new FileWriter(csvFilePath), BUFFER_SIZE)) { writeHeader(writer, coordVars, variableName); processData(writer, coordVars, mainVar, totalSize, dimOrderMap); System.out.println("Data written to CSV: " + csvFilePath); } } catch (IOException e) { SFIToolkit.errorln(SFIToolkit.stackTraceToString(e)); } } private static long calculateTotalSize(List<Variable> coordVars) { long totalSize = 1; for (Variable coordVar : coordVars) totalSize *= coordVar.getSize(); return totalSize; } private static void writeHeader(BufferedWriter writer, List<Variable> coordVars, String variableName) throws IOException { for (Variable coordVar : coordVars) writer.write(coordVar.getShortName() + ","); writer.write(variableName + "\n"); } private static void processData(BufferedWriter writer, List<Variable> coordVars, Variable mainVar, long totalSize, Map<Variable, Integer> dimOrderMap) throws IOException { StringBuilder sb = new StringBuilder(); int[] shape = new int[mainVar.getRank()]; List<Dimension> dims = mainVar.getDimensions(); for (int i = 0; i < dims.size(); i++) shape[i] = dims.get(i).getLength(); int[] dimIndexes = new int[coordVars.size()]; for (int i = 0; i < coordVars.size(); i++) dimIndexes[i] = dimOrderMap.get(coordVars.get(i)); List<double[]> coordCache = new ArrayList<>(); for (Variable var : coordVars) coordCache.add((double[]) var.read().get1DJavaArray(double.class)); double[] mainValues = (double[]) mainVar.read().get1DJavaArray(double.class); for (long i = 0; i < totalSize; i++) { int[] indices = calculateIndices(i, shape); for (int j = 0; j < coordVars.size(); j++) { int actualDim = dimIndexes[j]; sb.append(coordCache.get(j)[indices[actualDim]]).append(","); } sb.append(mainValues[(int)i]).append("\n"); if (sb.length() > BUFFER_SIZE) { writer.write(sb.toString()); sb.setLength(0); } } if (sb.length() > 0) writer.write(sb.toString()); } private static int[] calculateIndices(long flatIndex, int[] shape) { int[] indices = new int[shape.length]; for (int i = shape.length-1; i >= 0; i--) { indices[i] = (int)(flatIndex % shape[i]); flatIndex /= shape[i]; } return indices; } } end