- PR -

ファイルロックについて

投稿者投稿内容
みーちく
大ベテラン
会議室デビュー日: 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」を開いて、閉じるまでロックをかけたいと思っております。

さくらばさんのソースを参考にテストしたいと思います。
テスト結果は、またご報告いたします。

ありがとうござました。

スキルアップ/キャリアアップ(JOB@IT)