- みーちく
- 大ベテラン
- 会議室デビュー日: 2002/08/29
- 投稿数: 131
|
投稿日時: 2003-01-10 15:07
こんにちわ。
みーちくと申します。
この頃すごく悩んでおります。皆様。ご教授願います。
[環境]
RedHat7.1
TOMCAT3.2.3
J2SDK1.4.1
[概要]
・ファイルをSJISで読み込み、ArrayListに格納
・格納されたArrayListより、引数で渡されたstr変数のチェック
同じ値が存在していたら 削除
存在していなかったら ArrayListに追加
・ArrayListをファイルに書込み
この一連の動作をする時に、ファイルをロックしたいと考えておりますが、
ロックの方法がよくわかりません。
FileChannelにロックがあったのですが、使い方がよくわかりません。
皆様どうか、ご教授願います。
宜しくお願い致します。
| コード: |
|
public static boolean native(String str, String url){
ArrayList param_check = new ArrayList();
String ss = "";
BufferedReader fin;
BufferedWriter bw;
String n = "\r\n";
try {
/* [入力] */
fin = new BufferedReader(new InputStreamReader(new FileInputStream(url), "SJIS"));
while ((ss = fin.readLine()) != null) {
param_check.add(ss);
}
fin.close();
/* [check] */
int s = param_check.indexOf(str);
if(s == -1){
param_check.add(str);
System.out.println(param_check);
} else {
param_check.remove(s);
System.out.println(param_check);
}
/* [出力] */
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(url), "SJIS"));
for(int i=0; i<param_check.size(); i++){
bw.write((String)param_check.get(i) + n);
}
bw.close();
return true;
} catch (Exception ex) {
System.out.println("native faild: " + ex);
System.exit(1);
return false;
}
}
|
|
- raccoon
- ベテラン
- 会議室デビュー日: 2002/12/18
- 投稿数: 58
|
投稿日時: 2003-01-10 18:22
こんにちは。raccoonといいます。
FileChannelは,ファイルをメモリにマッピングして扱う機能であり,C言語のMapped File(UNIXのmmap,VC++のCreateFileMapping)相当のもののはずです。
したがって,通常のFileInputStreamなどとは扱い方も違いますが,それ以上に用途(=目的)が違います。
ですから,FileChannelを使うかどうか,という前に,システムとして,これは通常ファイルでreadすべきものなのか,Mapped Fileとして読み込むべきものなのか,を考える必要があると思います。
# 個人的には,「ロックしたいから」という理由だけでMapped Fileにするのはどうかと・・・。
# ちなみに,わたしの周りでは"Mapped File"または"Map File"という
# 呼び方が定着していますが,これはたぶん正式な呼び方ではありません。
# どなたか正式な呼び方を知っていたら,教えてください。
わたしも以前,Javaでプロセス間排他を取る方法がどうしてもなくて,やむを得ずJNIにした経験があります。(当時はFileChannelもありませんでしたし)
当時のキオクでは,「Javaは,VM内ですべてを制御するという思想のため,VM(=プロセス)を跨っての排他処理などは不可能」なのだと理解しました。
Mapped Fileは,もともと多プロセスで情報を共有するのが目的なので,「イレギュラであっても,FileChannelにはロックが必須」と判断したのだと思います。
# あれっ,なんか質問の回答になってませんね。
# 一応,コメントということでご勘弁を・・・
|
- teto
- ベテラン
- 会議室デビュー日: 2002/07/31
- 投稿数: 61
|
投稿日時: 2003-01-10 19:08
少し前にjavaのファイルロックで苦労しので検索してみました。
http://www5.airnet.ne.jp/sakuraba/java/laboratory/JDK1.4/NewIO/FileChannel/FileChannel.html
の「ロック」あたりにいろいろかかれてますね。
googleって便利。
|
- みーちく
- 大ベテラン
- 会議室デビュー日: 2002/08/29
- 投稿数: 131
|
投稿日時: 2003-01-10 19:38
raccoonさん、tetoさん
返信ありがとうございました。
私も教えて頂いたのサイトを参考に、がんばっているのですが、うまくいっておりません。
ByteBufferを使用して、バッファリングはうまくいっているのですが、前にも書きましたが
下記のチェックをする為に、ArrayListを使用しております。
ここでうまくArrayListに格納されてくれません。
[aa,bb,cc,ddd,e,ffff,]と入ってくれるとよいのですが
[aabbccddeffff]となってしまいます。
・格納されたArrayListより、引数で渡されたstr変数のチェック
同じ値が存在していたら 削除
存在していなかったら ArrayListに追加
良い方法などありましたら、宜しくお願い致します。
|
- さくらば
- 大ベテラン
- 会議室デビュー日: 2002/11/12
- 投稿数: 145
|
投稿日時: 2003-01-11 02:25
こんにちは。
http://www5.airnet.ne.jp/sakuraba/java/
の作者です。
ファイルロックは簡単だと思うんですけど。単に FileChannel#lock を使
うだけです。
ところで、FileChannel はファイルをマップさせるときに使うだけでなく、
ごくごく普通の入出力に使えますよ。
ストリームよりいろいろと機能があったり、パフォーマンスも高いので、
J2SE v1.4 を使うのであれば積極的に使うべきだと思います。
| 引用: |
|
みーちくさんの書き込み (2003-01-10 19:38) より:
ByteBufferを使用して、バッファリングはうまくいっているのですが、前にも書きましたが
下記のチェックをする為に、ArrayListを使用しております。
ここでうまくArrayListに格納されてくれません。
[aa,bb,cc,ddd,e,ffff,]と入ってくれるとよいのですが
[aabbccddeffff]となってしまいます。
|
こちらの理由はこれだけではよく分かりません。どのようなファイルを読
み込んで、str にはどのような文字列が入るのでしょうか。
ところで、native というのは予約語なので、メソッド名には使えないの
です ^^;;
一応、サンプルを載せておきます。みーちくさんは v1.4.1 をお使いなの
で問題はないのですが、Charset クラスで Shift_JIS がサポートされたの
は J2SE v1.4.1 からなので v1.4.0 では動作しません。
| コード: |
|
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;
import javax.swing.*;
public class LockSample {
public LockSample(String str, String url) {
List param_check = new ArrayList();
try {
Charset charset = Charset.forName("Shift_JIS");
CharsetEncoder encoder = charset.newEncoder();
CharsetDecoder decoder = charset.newDecoder();
/* [入力] */
RandomAccessFile raFile = new RandomAccessFile(url, "rw");
FileChannel channel = raFile.getChannel();
// buffer は多めにとっておく
ByteBuffer buffer = ByteBuffer.allocate((int)channel.size() * 2);
channel.read(buffer);
buffer.flip();
String contents = decoder.decode(buffer).toString();
StringTokenizer tokenizer = new StringTokenizer(contents, "\n");
while (tokenizer.hasMoreTokens()) {
param_check.add(tokenizer.nextToken());
}
/* [check] */
int s = param_check.indexOf(str);
if(s == -1){
param_check.add(str);
} else {
param_check.remove(s);
}
System.out.println(param_check);
/* [出力] */
encoder.reset();
buffer.clear();
int i;
for (i = 0 ; i < param_check.size() - 1 ; i++) {
encoder.encode(CharBuffer.wrap((String)param_check.get(i) + "\n"), buffer, false);
}
encoder.encode(CharBuffer.wrap((String)param_check.get(i)), buffer, true);
buffer.flip();
channel.truncate(0);
channel.write(buffer);
channel.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
new LockSample(args[0], args[1]);
}
}
|
|
- さくらば
- 大ベテラン
- 会議室デビュー日: 2002/11/12
- 投稿数: 145
|
投稿日時: 2003-01-11 03:43
肝心のロックの部分が入っていないバージョンをつけてしまいました。
すいませんが、前のは見なかったことにしてください ^^;;
| コード: |
|
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;
public class LockSample {
public LockSample(String str, String url) {
List param_check = new ArrayList();
try {
Charset charset = Charset.forName("Shift_JIS");
CharsetEncoder encoder = charset.newEncoder();
CharsetDecoder decoder = charset.newDecoder();
/* [入力] */
RandomAccessFile raFile = new RandomAccessFile(url, "rw");
FileChannel channel = raFile.getChannel();
// ここで排他ロック
FileLock lock = channel.lock();
// シェアードロックにするには次のようにする
// 第 1 引数 ロックの開始位置
// 第 2 引数 ロックの終端位置
// 第 3 引数 true: シェアードロック false: 排他ロック
// channel.lock(0, Long.MAX_VALUE, true);
// buffer は追加する分を考慮して多めにとっておく
ByteBuffer buffer = ByteBuffer.allocate((int)channel.size() * 2);
channel.read(buffer);
buffer.flip();
String contents = decoder.decode(buffer).toString();
StringTokenizer tokenizer = new StringTokenizer(contents, "\n");
while (tokenizer.hasMoreTokens()) {
param_check.add(tokenizer.nextToken());
}
/* [check] */
int s = param_check.indexOf(str);
if(s == -1){
param_check.add(str);
} else {
param_check.remove(s);
}
System.out.println(param_check);
/* [出力] */
encoder.reset();
buffer.clear();
int i;
for (i = 0 ; i < param_check.size() - 1 ; i++) {
encoder.encode(CharBuffer.wrap((String)param_check.get(i) + "\n"), buffer, false);
}
encoder.encode(CharBuffer.wrap((String)param_check.get(i)), buffer, true);
buffer.flip();
channel.truncate(0);
channel.write(buffer);
channel.close();
// ロックをリリースする
lock.release();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
new LockSample(args[0], args[1]);
}
}
|
|
- unibon
- ぬし
- 会議室デビュー日: 2002/08/22
- 投稿数: 1532
- お住まい・勤務地: 美人谷 良回答(20pt)
|
投稿日時: 2003-01-11 07:54
unibon です。こんにちわ。
どのファイルをいつからいつまでロックされたいのでしょうか。
コンピュータ一般には、ファイルは open すれば close するまでの間は
共有ロック以上のロックがかかっていることが多いので、
たとえば出力ファイルを close するまで入力ファイルを close しなければ、
それで十分だったりすることもあります。
|
- みーちく
- 大ベテラン
- 会議室デビュー日: 2002/08/29
- 投稿数: 131
|
投稿日時: 2003-01-12 14:28
さくらばさん、unibonさん
返信ありがとうござました。
まさか作者の方から、返信していただくとは思ってもおりませんでした。
また、詳しいサンプルまで付けて頂いて大変感謝しております。m(__)m
もうちょっと詳しく概要を説明させて頂きます。
[概要]
・申請プログラムより、新規申請
・申請された内容をDBに登録
・DBに申請された内容を「test.txt」に書き込み
・ファイルをSJISで読み込み、ArrayListに格納
・格納されたArrayListより、引数で渡されたstr変数のチェック
同じ値が存在していたら 削除
存在していなかったら ArrayListに追加
・ArrayListをファイルに書込み
申請者は複数存在してしまうので、ファイルをロックしたいと考えております。
「test.txt」を開いて、閉じるまでロックをかけたいと思っております。
さくらばさんのソースを参考にテストしたいと思います。
テスト結果は、またご報告いたします。
ありがとうござました。
|