5

私はこれに対する答えを探していましたが、見つかりませんでした。誰かがこの種の問題の解決策を持っていますか?Javaを使用して.CSVファイルに書き込む必要のある一連のテキスト変数があります。私は現在、Javaを呼び出すJavaScriptを使用したプロジェクトを行っています。これは私が今持っている関数で、うまく機能し、テキストを.CSVに1行ずつ書き込みます。

function writeFile(filename, data)
{
   try
   { 

      //write the data

      out = new java.io.BufferedWriter(new java.io.FileWriter(filename, true));
      out.newLine();
      out.write(data);
      out.close();
      out=null;
   }
   catch(e)   //catch and report any errors
   {
      alert(""+e);
   }
}

しかし今、私は以下の例のようにテキストの一部を一つずつ書かなければなりません。

first0,second0,third0
first1,second1,third1
first2,second2,third2
.
.
.
first9,second9,third9

したがって、アルゴリズムは次のようになります。関数はfirst0をコンマで書き込み、次に次の行に移動してfirst1を書き込み、次の行に移動してfirst2を書き込み、1つをfirst9まで書き込みます。その部分が完了した後、スクリプトはファイルの先頭に移動してコンマの後ろにsecond0を書き込み、次の行に移動してコンマの後ろにsecond1を書き込みます。あなたはその考えを理解します。

だから今私はJavaが必要です

4

5 に答える 5

4

スーパーCSVを使用してCSVファイルを作成することを検討することをお勧めします。埋め込まれた二重引用符とコンマのエスケープを処理するだけでなく、配列/リスト、マップ、さらにはPOJOから書き込むさまざまな書き込み実装を提供します。これは、アイデアを簡単に試すことができることを意味します。

本当にシンプルにしたい場合は、CSVファイルを2次元配列にアセンブルできます。これにより、最初に列を組み立てて、準備ができたらすべてをCSVに書き込むことができます。

package example;

import java.io.FileWriter;
import java.io.IOException;

import org.supercsv.io.CsvListWriter;
import org.supercsv.io.ICsvListWriter;
import org.supercsv.prefs.CsvPreference;

public class ColumnFirst {

    public static void main(String[] args) {

        // you can assemble this 2D array however you want
        final String[][] csvMatrix = new String[3][3];
        csvMatrix[0][0] = "first0";
        csvMatrix[0][1] = "second0";
        csvMatrix[0][2] = "third0";
        csvMatrix[1][0] = "first1";
        csvMatrix[1][1] = "second1";
        csvMatrix[1][2] = "third1";
        csvMatrix[2][0] = "first2";
        csvMatrix[2][1] = "second2";
        csvMatrix[2][2] = "third2";

        writeCsv(csvMatrix);

    }

    private static void writeCsv(String[][] csvMatrix) {

        ICsvListWriter csvWriter = null;
        try {
            csvWriter = new CsvListWriter(new FileWriter("out.csv"), 
                CsvPreference.STANDARD_PREFERENCE);

            for (int i = 0; i < csvMatrix.length; i++) {
                csvWriter.write(csvMatrix[i]);
            }

        } catch (IOException e) {
            e.printStackTrace(); // TODO handle exception properly
        } finally {
            try {
                csvWriter.close();
            } catch (IOException e) {
            }
        }

    }

}

出力:

first0,second0,third0
first1,second1,third1
first2,second2,third2
于 2012-09-24T00:20:26.860 に答える
2

これが問題に対する私の解決策です。低レベルのランダムアクセスファイルメカニズムのおかげで、データ全体をバッファに保持する必要はありません。それでも、レコードを1つずつロードする必要があります。

package file.csv;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.List;

public class CsvColumnWriter {

    public static void main(String args[]) throws Exception{

        CsvColumnWriter csvWriter = new CsvColumnWriter(new File("d:\\csv.txt"), new File("d:\\csv.work.txt"), 3);

        csvWriter.writeNextCol(Arrays.asList(new String[]{"first0", "first1", "first2"}));
        csvWriter.writeNextCol(Arrays.asList(new String[]{"second0", "second1", "second2"}));
        csvWriter.writeNextCol(Arrays.asList(new String[]{"third0", "third1", "third2"}));

    }

    public void writeNextCol(List<String> colOfValues) throws IOException{
        // we are going to create a new target file so we have to first 
        // create a duplicated version
        copyFile(targetFile, workFile);

        this.targetStream = new BufferedOutputStream(new FileOutputStream(targetFile));

        int lineNo = 0;

        for(String nextColValue: colOfValues){

            String nextChunk = nextColValue + ",";

            // before we add the next chunk to the current line, 
            // we must retrieve the line from the duplicated file based on its the ofset and length 
            int lineOfset = findLineOfset(lineNo);  

            workRndAccFile.seek(lineOfset);

            int bytesToRead = lineInBytes[lineNo];
            byte[] curLineBytes = new byte[bytesToRead];
            workRndAccFile.read(curLineBytes);

            // now, we write the previous version of the line fetched from the
            // duplicated file plus the new chunk plus a 'new line' character
            targetStream.write(curLineBytes);
            targetStream.write(nextChunk.getBytes());
            targetStream.write("\n".getBytes());

            // update the length of the line
            lineInBytes[lineNo] += nextChunk.getBytes().length; 

            lineNo++;
        }

        // Though I have not done it myself but obviously some code should be added here to care for the cases where 
        // less column values have been provided in this method than the total number of lines

        targetStream.flush();
        workFile.delete();

        firstColWritten = true;
    }

    // finds the byte ofset of the given line in the duplicated file
    private int findLineOfset(int lineNo) {  
        int ofset = 0;
        for(int i = 0; i < lineNo; i++)
            ofset += lineInBytes[lineNo] + 
                (firstColWritten? 1:0); // 1 byte is added for '\n' if at least one column has been written
        return ofset;
    }

    // helper method for file copy operation
    public static void copyFile( File from, File to ) throws IOException {
            FileChannel in = new FileInputStream( from ).getChannel();
            FileChannel out = new FileOutputStream( to ).getChannel();
            out.transferFrom( in, 0, in.size() );
    }

    public CsvColumnWriter(File targetFile, File workFile, int lines) throws Exception{
        this.targetFile = targetFile;
        this.workFile = workFile;

        workFile.createNewFile();

        this.workRndAccFile = new RandomAccessFile(workFile, "rw");

        lineInBytes = new int[lines];
        for(int i = 0; i < lines; i++)
            lineInBytes[i] = 0;

        firstColWritten = false;
    }

    private File targetFile;
    private File workFile;

    private int[] lineInBytes;
    private OutputStream targetStream;
    private RandomAccessFile workRndAccFile;
    private boolean firstColWritten;

}
于 2012-09-24T02:57:27.777 に答える
0

エラーが発生した場合にデータを失わないという要件に基づいて、おそらく設計を再考し、組み込みデータベースを使用する必要があります(Embedded javaデータベースでさまざまな組み込みデータベースのメリットについて説明しています)。データベースに必要なテーブルは1つだけです。

元の質問では、任意の行の列を任意の順序で更新できるデータベースのようなCSVファイルを使用しようとしているように思われるため、これをお勧めします。その場合は、弾丸を噛んで実際のデータベースを使用してみませんか。

とにかく、テーブルのすべての列と行を入力したら、データベースを「テキストファイルの順序」row1-col1、row1-col2...row2-col1などのCSVファイルにエクスポートします。

データベースの構築中、または少なくともCSVファイルのエクスポート中にエラーが発生した場合でも、前回の実行からのすべてのデータが残っているため、再試行できます。

于 2012-09-24T00:03:51.300 に答える
0

これはどう

        Scanner input = new Scanner(System.in);
        String[] lines = new String[9];

        for (int j = 0; j < 2; j++) {
            for (int i = 0; i < 9; i++) {
                lines[i] += (String) input.nextLine() + ",";
            }
        }
        for (int i = 0; i < 9; i++) {
            lines[i] += (String) input.nextLine();
        }
于 2012-09-23T23:31:53.473 に答える
0

私は先に進んでおり、このタスクを実行する方法にある程度の自由があると想定しています。私の知る限り、ファイルにテキストを「挿入」することはできません。これを行うには、ファイルを完全に読み取り、メモリ内で変更してから、結果をファイルに書き戻す必要があります。

したがって、メモリ内のデータ構造を反転してから書き込むとよいでしょう。データオブジェクトが行列の場合は、転置するだけで、書きたい形式になります。

于 2012-09-23T23:14:02.743 に答える