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>
コメント
コメントを投稿