CSV ファイルへの読み書き時の注意

ドミノのアプリケーションでは、他システムとのやりとりやワークファイルなどに CSV ファイルが使われているケースがよくあります。

iSeries のドミノでこうしたアプリケーションを稼動させる場合は、iSeries の使用している文字コードが EBCDIC という少なくともマジョリティではないものであるがゆえに、いくつか問題に遭遇することがあります。

ここではそういうケースに典型的にどういう問題があるか、解決策にはどういうやり方があるか、をちょっと簡単に紹介してみたいと思います。


データベースとエージェントの内容

テスト用に簡単なデータベースを作成しました。

テストする文書にはテキストが 3つと数字が 1つ。

表示のためのビューと、エージェント起動のためのアクションを定義します。

アクションの名前にあわせて CSV を読み書きするエージェントをそれぞれロータススクリプトと Java で書きます。

まず最初にノーツの文書をファイルに書き出すロータススクリプトエージェント WriteTest (LS) です。

こちらがそのファイルをもういちど読んで、ノーツ文書として格納するロータススクリプトエージェント ReadTest (LS) です。

こちらが先のファイル書き出し用のロータススクリプトエージェントを Java で書き直したもの WriteTest (Java) です。

Java は全文を写しきれなかったので、こちらがその全文です。

import lotus.domino.*;
import java.io.*;

public class JavaAgent extends AgentBase {

public void NotesMain() {

try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();

// (Your code goes here)
Database db = agentContext.getCurrentDatabase();
View view = db.getView("TestView");
Document doc = view.getFirstDocument();

File file = new File("test001.csv");
if (file.exists())
{ }
else {
OutputStreamWriter fwtemp = new OutputStreamWriter(new FileOutputStream(file), "Cp943c");
fwtemp.write("Create New File with CCSID 943");
PrintWriter pwtemp = new PrintWriter(fwtemp);
fwtemp.close();
pwtemp.close();
}

OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(file), "MS932");
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);

while (doc != null) {
int number = doc.getItemValueInteger("number");
String text1 = doc.getItemValueString("text1");
String text2 = doc.getItemValueString("text2");
String text3 = doc.getItemValueString("text3");

String line = number + "," + text1 + "," + text2 + "," +text3;

bw.write(line);
bw.newLine();
doc = view.getNextDocument(doc);
}

bw.close();
fw.close();
pw.close();


} catch(Exception e) {
e.printStackTrace();
}
}
}

ファイル読み込み用のロータススクリプトエージェントを Java で書き直したもの ReadTest (Java) です。

こちらが全文です。

import lotus.domino.*;
import java.io.*;
import java.util.*;

public class JavaAgent extends AgentBase {

public void NotesMain() {

try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();

// (Your code goes here)
Database database = agentContext.getCurrentDatabase();
File file = new File("test001.csv");
InputStreamReader filereader = new InputStreamReader(new FileInputStream(file), "MS932");
BufferedReader bufferedreader = new BufferedReader(filereader);

String line;
int i = 1;
int j = 0;

String number = null;
String text1 = null;
String text2 = null;
String text3 = null;

while((line = bufferedreader.readLine()) != null) {
System.out.println(line);
j = 0;
StringTokenizer stringTokenizerTest = new StringTokenizer(line, ",");
while(stringTokenizerTest.hasMoreTokens()) {
switch(j) {
case 0:
number = stringTokenizerTest.nextToken().toString();
System.out.println(number);
break;
case 1:
text1 = stringTokenizerTest.nextToken().toString();
System.out.println(text1);
break;
case 2:
text2 = stringTokenizerTest.nextToken().toString();
System.out.println(text2);
break;
case 3:
text3 = stringTokenizerTest.nextToken().toString();
System.out.println(text3);
break;
//default:
// System.out.println("Error");
}
j++;
}
Document document = database.createDocument();
document.replaceItemValue("Form", "testform");
document.replaceItemValue("number", number);
document.replaceItemValue("text1", text1);
document.replaceItemValue("text2", text2);
document.replaceItemValue("text3", text3);
document.save();
document.recycle();
i++;
}

filereader.close();


} catch(Exception e) {
e.printStackTrace();
}
}
}

このデータベースにデータを入力して、ブラウザからビューを開いた画面です。

ロータススクリプトエージェントの場合の問題点

WriteTest (LS) を実行した結果です。

ファイル test0001.csv ができているのが確認できます。

属性をみてみると CCSID 1027 という EBCDIC のコードページになっています。

内容を見てみましょう。
ちょっとわかりにくいかもしれませんが、いくつかの文字が変換されずにブランクになっています。

ReadTest (LS) で今書き出したファイルから再度読み込みを行ない、ノーツデータベースに格納して表示します。

先程ファイルで見て変換されていなかった文字が「・」になっています。

NEC 選定文字という文字が 83文字ありますが、このうち 13文字が IBM 選定文字と重複し、9文字が JIS非漢字と重複しています。
この 22文字に関しては EBCDIC (iSeries のネイティブの文字コード) に対応する文字セットとコードポイントが存在しますが、残りの 61文字は EBCDICに文字(文字セット+コードポイント)が存在しないため、変換することができません。

また、この作成された test001.csv ファイルの属性が EBCDIC であることから確認できるように、内容が EBCDIC コードで書かれたファイルになっています。
これはこのファイルをそのままネットワークドライブ経由やバイナリーの FTP で転送しての使用ができない、ということを意味します。
通常こういった CSV ファイルへの書き出しなどは、他システム (多くは PC ですね) とのやりとりのために生成されるものです。内容が EBCDIC でエンコードされている、というのはかなり問題でしょう。

Java エージェントによる解決策

そこで、Java エージェントでの書き直しということになります。

Java エージェントの方が若干長くなっていますが、そんなに難しくはないでしょう。

WriteTest (Java) の実行結果です。

ちゃんと test001.csv は作成されていますね。

CCSID が 943 になっているのが確認できます。

内容を見てみましょう。

正しく文字が変換されているのが確認できます。

ReadTest (Java) でもういちどファイルから読み直してみても、そのまま正しい文字になっているのが確認できます。

[Top Pageに戻る]

Ads by TOK2