ファイルと応用

「ファイル」は文字や数値を記録した電子的記録です。ここでは、Processing でファイルを作成したり、読みこむ方法を紹介します。


  1. ファイルの文字列を読む

     「ファイル」 pos.txt には、予め次のような文字を記録しておきます(同じ形式のファイルを次のファイル保存で作成しますから、それをコピーすることも可能です)。各行の最初の数字は x座標、次は y座標です。数字の間は , で分割しておきます。このように 複数の項目を , などの区切り記号で分割されたファイルは 「csv ファイル」と呼ばれ、情報交換に良く利用されます。Excelなどの 表処理でも利用できます。ファイルはプログラムを保存したフォルダの内部に保存します。
     このファイルを読み取り、座標の位置に円でマークをするのが目的です。「ファイル」は このプログラムを保存したフォルダに配置します。
    12,35
    45,50
    56,30
    70,30
    85,46
    66,80
     setup()の中の loadString(<ファイル>)は文字を記録したファイルのすべての行を行単位に読みこみ、String 配列 lines[] に記録します。
     draw() の中では、lines[] から lin に1行を読み取り、split(<文字列>、<区切り記号>)で lin の文字を , で分割し、分割した各文字列を co[] に記録します。int(co[0]) で co[0] を整数に変換し x に保存します。同様に y も処理し、ellipse() で(x,y) 座標に円をマークします。
    String lin;
    int ln;
    String lines[];
    
    void setup() {
      //ファイルを文字列配列に lines 読み込む
      ln=0;
      lines = loadStrings("pos.txt");
    }
    
    void draw() {
       lin =lines[ln];//第 ln 行を読む
        // , で分割
        String[] co = split(lin, ',');
        if (co.length==2) {//x,y の2項目があれば
          //整数に変換
          int x = int(co[0]);
          int y = int(co[1]);
          ellipse(x, y, 3, 3);
        }
      ln++;
      //最後まで読んだら停止
      if(ln == lines.length) noLoop();
    }

     loadStrings("pos.txt");では、まとめて配列に記録するので、大きなファイルには適応できません。大きなファイルを読みながら、順に処理を進めるには BufferedReader を利用します。まず、createReader("pos.txt"); で reader を作成します。reader.readLine() でファイルから1行を読みます。readLine() はエラー処理に備えて、try{ } catch{ } 構文の中で行います。読み取り中にエラーがあると、catch のブロックが実行されます。e.printStackTrace(); はエラーが起きるまでの履歴を表示するメソッドです。 reader.readLine() は エラー処理が必須になっており省略できません。
    //ファイルを読み座標を表示
    BufferedReader reader;
    String line;
    
    void setup() {
      //ファイルを開く
      reader = createReader("pos.txt");
    }
    
    void draw() {
      line=null;
      try {
        //1行読む
        line = reader.readLine();
      } 
      catch (IOException e) {//エラー処理
        e.printStackTrace();
        println("読み取りエラー");
      }
     
      if (line == null) {
        //読み取り終了
        noLoop();
      } 
      else {
        // , で分割
        String[] co = split(line, ',');
        if (co.length==2) {
          //整数に変換
          int x = int(co[0]);
          int y = int(co[1]);
          ellipse(x, y, 3, 3);//円を表示
        }
        else println(line);// , なし
      }
    }
    実行結果(ファイルの内容で異なります)


  2. ファイルに文字で記録する

     マウスでクリックした座標を「ファイル」に記録する方法を紹介します。記録には PrintWriterを利用します。まず、createWriter() で指定の名前のファイルを作成し、outfile を作成します。draw() ではマウスが押されたとき(mousePressed)、その座標をマークするとともに、outfile に println() で文字列を記録します。
     終了はキーボードから s キーが押されたときとします。キーが押されたとき、flush() でデータを「ファイル」に出力します。
    //ファイル保存
    PrintWriter outfile;
    
    void setup() 
    {
      size(200, 200);
      // ファイルを作成する
      outfile = createWriter("pos.txt");
      frameRate(20);
    }
    
    void draw() 
    {
      if (mousePressed) {
        ellipse(mouseX, mouseY,3,3);
        // ファイルに記録する
        outfile.println(mouseX + "," + mouseY);
      }
    }
    
    void keyPressed() { 
      if(key == 's'){
        outfile.flush(); //残りを出力する
        outfile.close(); // ファイルを閉じる
        exit(); // 終了
      }
    }
     ファイル への実際の出力は println() の度に行うわけでなく、ある程度データが蓄積された段階で出力します。flush() は残りのデータを強制的に出力する指示です。その後、close() でファイルを閉じます。
     ファイルを読むときは、ファイルを「閉じる」処理は必須ではありませんが、記録するときは close() 処理は必須になります。ファイルは プログラム が記録されるフォルダに保存されます。
     String 配列に座標を記録しておき、saveString()ですべての文字列をファイルに保存することも可能です。この場合、十分な記憶領域の確保が必要です。

  3. 異なるフォルダーに記録する

     指定したフォルダにファイルを記録するには selectOutput() を利用します。これを実行すると、使用している OS のダイアログが実行され、フォルダとファイルの指定ができます。戻り値で「ファイルパス」が文字列で渡されますから、そのパスにファイルを出力します。下に、setup() のみを示します。
    void setup() 
    {
      size(200, 200);
      // ファイルを作成する
      String path = selectOutput();
      println(path);
      outfile = createWriter(path);
      frameRate(20);
    }
    ///ファイルパス(windows)の例
    E:\soft\processing\prIntro\SaveFile\data\pos.txt
    
     異なるフォルダのファイルを選択して読み込むするには、selectInput() を利用します。また、個別のファイルでなく、フォルダーを選択する場合は、selectFolder() が利用できます。
  4. 異なる文字コードでバイト単位で保存する

     Procesingでの文字コードは utf-8 です。String の文字コードを別の文字コードに変換するのは、getBytes(<文字コード>)を利用します。結果はバイト配列になります。バイト配列を可録するには、createOutput(<ファイル名>)でファイルを作成し、write(<バイト配列>)で書き込みます。
    //Shift JIS でファイル出力
    //getBytes で文字コードを変換し、バイト出力する
    
    String[] st= { "あいうえ", "漢字"};
    byte[] crlf="\r\n".getBytes("Shift_JIS");
    
    void setup() {
       OutputStream outfile;
     
      try {
        
        outfile = createOutput("SJIS.txt"); 
        //st[0]を Shift_JISコードのバイト列に変換しファイル出力 
        outfile.write(st[0].getBytes("Shift_JIS")); 
        //改行コードのバイト列をファイルに出力 
        outfile.write(crlf);
       
        outfile.write(st[1].getBytes("Shift_JIS"));  
        outfile.write(crlf);
        
        outfile.flush();
        outfile.close();
      }
      catch(IOException e) {
        System.out.println(e);
      }
    }

  5. 実行画面の画像記録

     実行画面(ディスプレイウインドウ)の画像は save(ファイル名); で保存できます。保存形式は、png,jpeg,tiff で指定するファイルの拡張子で定まります。次に、記録プログラムに . キーを押したら、hc00.png、hc01.png、と hcxx の名前で png 型のファイルに保存する例を示します。変数 no の宣言と初期化が必要です。
    void keyPressed() { 
      if(key == 's'){
        outfile.flush(); //残りを出力する
        outfile.close(); // ファイルを綴じる
        exit(); // 終了
      }
      if(key == '.'){
        save("hc"+no+".png");
        println("save:"+no);
        no++;
      }
    }

  6. まとめ

     ファイルへの保存には、文字列で出力する場合とバイト単位で記録する方法があります。バイト単位の方が効率的ですが、ファイルの内容を確認するには専用のプログラムが必要です。文字列で保存する場合、文字列配列にまとめて読み込む(保存する)方法と行単位で保存する方法があります。