Javaデモ/JSPages「ファイル入出力、ファイル・ロック」:「RandomAccessFile、FileChannel、Charset、ByteBuffer」(Ver.2)

開発環境はEclipseです。

Eclipseにおいてサーバー・サイド用Javaプロジェクトを作る場合は「動的Web」でプロジェクトを作る必要が有ります。

「動的Web」プロジェクト作成時には、必ず「web.xmlデプロイメント記述子の生成」チェックボックスをチェックしてして下さい(下記参照)。


Webアプリ向け開発手順

http://www.javaroad.jp/opensource/js_eclipse6.htm


現在、文字エンコードは多数ありますが、「UTF-8、Shift_JIS」の2つがインターネットでのデファクト・スタンダードですが、Windowsの場合はShift_JISとは微妙に違うMS932(CP932)がデファクト・スタンダードになります(なのでWindowsにおいてShift_JISと言う場合は、基本的にMS932(CP932)を意味します)。

指定されている文字エンコードとセーブ時の文字エンコードが違うと全角文字が文字化けするので注意して下さい。


【このデモの略説】


新規データをファイルの先頭に追加して行きます。


サーバー・サイドの場合、多数のユーザーが同時にアクセスした場合を考慮する必要があります。

具体的にはサーバー・サイドの場合は、ファイル出力時にファイルをロックしないとデータ破壊される危険性があります。

また ファイルの書き換え(ファイル入力してファイル出力する)は、ファイル入出力を一体としてロックしないとデータ破壊される危険性があります、つまり ファイル入力とファイル出力でファイル・ロックを2つに分けるとファイル・データが破壊される危険性があります。

下記デモでもファイル入力とファイル出力でファイル・ロックは1つだけだと言うことに注意して下さい。


try-with-resources文を使っているので自動クローズがサポートされるので、クローズを明記する必要は有りません。

クローズすると自動的にロックも解除されるので、ロックの解除も明記する必要は有りません。

「oRWChannel.truncate(0);」は一旦ファイル・サイズをゼロにしています。

そうしないと(記事を削除した場合など)以前よりファイル・サイズを小さくしたい場合に、前のデータが残ってしまいます。



【WebContent/MyJSPages.jsp】

※既存の「WebContent」フォルダ内に作成します。


<%@ page language="java" contentType="text/html; charset=UTF-8"

  pageEncoding="UTF-8"%>

<%@ page import="java.io.IOException"%>

<%@ page import="java.io.BufferedReader"%>

<%@ page import="java.io.BufferedWriter"%>

<%@ page import="java.io.FileInputStream"%>

<%@ page import="java.io.FileOutputStream"%>

<%@ page import="java.io.InputStreamReader"%>

<%@ page import="java.io.OutputStreamWriter"%>

<%@ page import="java.io.OutputStreamWriter"%>

<%@ page import="java.nio.charset.Charset"%>

<%@ page import="java.io.RandomAccessFile"%>

<%@ page import="java.util.Arrays"%>

<%@ page import="java.util.List"%>

<%@ page import="java.util.ArrayList"%>

<%@ page import="java.nio.channels.FileChannel"%>

<%@ page import="java.nio.ByteBuffer"%>

<%

String sASC_LF = String.valueOf((char) 0x0A); // Line Feed.

String sASC_CR = String.valueOf((char) 0x0D); // Carriage Return.

String sTextIndention = sASC_CR;


String sReg_Indention = "(\\x0D\\x0A|\\x0D|\\x0A)";

// このデモでは改行コード(sTextIndention)は「x0D」しか使ってないが、

// OSによって改行コードが違うので、正規表現で文字列を分割している。


String encode = "UTF-8";


int iArticle_Max = 5;

// 記事の最大件数を5件に制限している


request.setCharacterEncoding(encode);

String sArticle = request.getParameter("Article");

if(sArticle==null) //

  System.out.println("if(sArticle==null)");


String file = "C:/pleiades/file.txt";

Charset oCharset = Charset.forName(encode);


List<String> dlsArticle = new ArrayList<String>();

String sBuffer, sNewBuffer, sMsg;

sMsg = "";

sBuffer = "";

sNewBuffer = "";

try ( // これはtry-with-resources文なので、

    // 自動クローズがサポートされるから、明示的なクローズは必要ない。


    RandomAccessFile oRWFile = new RandomAccessFile(file, "rw");

    // 読み書き可能なFile


    FileChannel oRWChannel = oRWFile.getChannel(); //

) {

  oRWChannel.lock();

  ByteBuffer oByteBuffer;


  oByteBuffer = ByteBuffer.allocate((int) oRWChannel.size());

  // oRWChannel.size()が約2GB(2,147,483,647Byte)を超えたらダメ。


  oRWChannel.read(oByteBuffer);

  oByteBuffer.rewind();

  sBuffer = oCharset.decode(oByteBuffer).toString();


  if (!(null == sBuffer || "".equals(sBuffer))) {

    dlsArticle = new ArrayList(Arrays.asList(sBuffer.split(sReg_Indention)));

        // Arrays.asList(sBuffer.split(sReg_Indention));

  }


  System.out.printf("sArticle: %s%n", sArticle);


  boolean edit = !(null == sArticle || "".equals(sArticle));

  if (edit) {

    dlsArticle.add(0, sArticle);

    System.out.printf("dlsArticle: %s%n", dlsArticle);

  }


  for (int i = 0; i < Math.min(dlsArticle.size(), iArticle_Max); i++) {

    sNewBuffer += (i != 0 ? sTextIndention : "") + dlsArticle.get(i);


    sMsg += dlsArticle.get(i) + "<br>";

    // 実際は特殊文字に対応する変換が必要

  }

  System.out.printf("sMsg: %s%n", sMsg);


  if (edit) {

    oByteBuffer = oCharset.encode(sNewBuffer);

    oByteBuffer.rewind();


    oRWChannel.truncate(0);

    // 一旦 ファイル・サイズをゼロにしている。


    oRWChannel.write(oByteBuffer);

  }

} catch (IOException ex) {

  ex.printStackTrace();

} finally {

}

%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>title</title>

</head>

<body>

  <form method="post">

    <input type="text" name="Article">

    <input type="submit" value="送信"><br>

  </form>

  <div>

    <%=sMsg%>

  </div>

</body>

</html>


コメント

このブログの人気の投稿