【Java】JSPでタグライブラリを使う(JSTL)
こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ
Workteria(ワークテリア)では難易度の高いものから低いものまで、スキルや経験に合わせた案件を多数揃えています。会員登録は無料ですので、ぜひ会員登録してご希望の案件を探してみてください!
フリーランス/正社員のエンジニアとして活躍するには、ご自身のスキルや経験に合わせた仕事を選ぶことが大切です。ご希望の案件がみつからない場合はお気軽にお問い合わせください!ユーザ満足度の高いキャリアコンサルタントが在籍していますので、希望条件や悩み事などなんでもご相談ください。ご希望にピッタリの案件をご紹介させていただきます。
当記事では、Javaにおけるテキストファイルの読み書きの方法について説明します。Javaにおけるバイナリファイルの読み書きの方法については、以下の記事を参照してください。
似たような名前のクラスがいろいろあり、Javaの初学者は戸惑うこともあるかもしれませんが、それぞれのクラスには役割や働きに応じたクラス名が付いていますので、そこを理解できれば使い分けも簡単になると思います。よく起こりがちなエラーへの対処法も含めて、Java Gold SE 11の資格を持つ著者が解説したいと思います。
文字コードという枠組みに沿って書かれた、文字を表すファイルをテキストファイルといい、Javaにおけるテキストファイルの読み書きには文字ストリームという仕組みを扱います。文字コード、文字ストリームについての詳しい解説は、以下の記事を参照してください。
Javaにおけテキストファイルの読み取りには、java.ioパッケージのReaderを継承したクラスを用い、出力にはWriterを継承したクラスを使います。Javaには、テキストファイルを扱う様々なクラスが用意されていますが、当記事では以下のよく使われるクラスについて解説します。
・FileReader / FileWriter
・BufferedReader / BufferedWriter
・PrintWriter
・InputStreamReader / OutputStreamWriter
Javaにおいて文字ストリームを扱う抽象クラスであるReader、Writerには、それぞれいくつかのメソッドが用意されています。
Readerクラスのメソッドは以下の通りです。Readerを継承したクラスで呼び出すことが出来ます。
メソッド名 | 返り値の型 | 説明 |
---|---|---|
read() | int | 入力ストリームから1文字ずつ読み取ります。ファイルの終わりに達したときは-1を返します。 |
read(char[] c) | int | 入力ストリームから引数に渡したchar配列cにデータをコピーします。返り値は読み取られた文字数です。ファイルの終わりに達したときは-1を返します。 |
read(char[] c, int off, int len) | int | 入力ストリームから引数に渡したchar配列cにデータをコピーしますが、読み取り開始インデックスoffを指定し、そこから読み込む文字数lenだけ読み取ります。返り値は読み取られた文字数です。ファイルの終わりに達したときは-1を返します。 |
close() | void | ストリームをクローズして、メモリへの割り当てを解除します。 |
Writerクラスのメソッドは以下の通りです。Writerを継承したクラスで呼び出すことが出来ます。
メソッド名 | 返り値の型 | 説明 |
---|---|---|
write(int c) | void | 出力ストリームに1文字ずつ書き込みます。char型ではなくint型を引数に渡さなければなりません。 |
write(char[] c) | void | 出力ストリームに引数に渡したchar配列cを書き込みます。 |
write(char[] c, int off, int len) | void | 出力ストリームに引数に渡したchar配列cを書き込みますが、書き込みを開始するインデックスoffを指定し、そこから書き込む文字数lenだけ書き込みます。 |
write(String s) | void | 出力ストリームに引数に渡した文字列sを書き込みます。 |
write(String s, int off, int len) | void | 出力ストリームに引数に渡した文字列sを書き込みますが、書き込みを開始するインデックスoffを指定し、そこから書き込む文字数lenだけ書き込みます。 |
flush() | void | バッファに格納されている全ての出力文字ストリームを強制的に書き込みます。 |
close() | void | ストリームをクローズして、メモリへの割り当てを解除します。 |
Javaにおいて入出力ストリームのインスタンスを扱う際は、処理が終わった後に必ずclose()メソッドを実行して下さい。これを忘れると、使わないストリームにメモリが割り当てらたままになるメモリリークと呼ばれる状態になり、処理が遅くなるなどの不具合の原因となることがあります。
当記事では、サンプルコードにtry-with-resources構文を用いて処理が終わった後に自動的にclose()メソッドを実行するようにしています。そのため、try-with-resources構文について理解に不安がある方は以下の記事を参照してください。
【Java】try - with - resources 構文
よくあるエラーとして、「FileNotFoundException」という例外が起こることがあります。これはJavaにおいてファイルのパスの場所を間違えて指定した場合などに起きます。パスは絶対パスと相対パスの2種類の表記法がありますが、慣れないうちは絶対パスで指定すると間違いが少なくなります。
ファイルの絶対パスを正確かつ簡単に取得したいときは、指定したいファイルのあるフォルダで、上部のバーを右クリックして「アドレスをテキストとしてコピー」という項目を選択して絶対パスをコピーします。
例えば、上記の画面で操作を行った場合、「C:\JavaWorkspace\Works」というディレクトリの絶対パスがコピーされますが、「\」はエスケープ文字を表す文字なので、Javaに「\」を認識させたい場合は「\」を「\\」と入力する必要があります。例えば、Worksディレクトリ内の「sample.jpg」の絶対パスを指定したい場合は、「C:\\JavaWorkspace\\Works\\sample.jpg」とする必要があります。Eclipse上では、文字列を表す「""」のダブルクォーテーションの間にコピーすれば自動的に「\」が「\\」に変換されます。
また、サンプルコードを実行したとき、「error='ページング ファイルが小さすぎるため、この操作を完了できません。' (DOS error/errno=1455)」というエラーメッセージが表示されることがあります。これは、Cドライブの空き容量が足りないために起こるので、十分な空き容量を確保してからコードを実行するようにしてください。
FileReaderは、ファイルから文字ストリームを作成するためのクラスです。
コンストラクタの引数にはパスを表す文字列、またはFileオブジェクトを取ります。
//コンストラクタに読み取るファイルのパスを表す文字列を渡します。絶対パスでも相対パスでも大丈夫です。
FileReader fr = new FileReader("ファイルのパス");
//コンストラクタにFileオブジェクトを指定することも出来ます。
File file = new File("ファイルのパス");
FileReader fr = new FileReader(file);
FileWriterは、ファイルに書き込みを行うための文字出力ストリームを作成するクラスです。FileReader同様、コンストラクタの引数にはファイルのパス名またはFileオブジェクトを取りますが、第二引数に「true」を指定することで追記を行うことも出来ます。
コンストラクタの引数にはパスを表す文字列、またはFileオブジェクトを取ります。
//コンストラクタに読み取るファイルのパスを表す文字列を渡します。絶対パスでも相対パスでも大丈夫です。
FileWriter fw = new FileWriter("ファイルのパス");
//FileWriterはデフォルトでは指定したファイルの内容をすべて書き換えますが、
//コンストラクタに2つ目の引数としてtrueを渡すと追記するように指定が出来ます。
FileWriter fw = new FileWriter("ファイルのパス", true);
//コンストラクタにFileオブジェクトを指定することも出来ます。
File file = new File("ファイルのパス");
FileWriter fw = new FileWriter(file);
//こちらも2つ目の引数としてtrueを渡すと追記するように指定が出来ます。
FileWriter fw = new FileWriter(file, true);
以下のテキストファイル「HelloWorld.txt」を例に、FileReader / FileWriterを使った、Javaにおけるテキストファイルの読み込みと出力についての解説を行います。
Hello, World!
メモ帳などのワードエディタで上記内容を入力し、「HelloWorld.txt」という名前で保存したテキストファイルを用意します。
import java.io.FileReader;
import java.io.FileWriter;
public class FileRWSample {
public static void main(String[] args) {
//try-with-resouses構文を使って、処理が終わった後に自動的にclose()メソッドを呼び出すようにします。
//「;」を使うことで、リソースを複数指定できます。
//読み込むファイルにHelloWorld.txt、書き出すファイル名にsample.txtを指定しています。
try (FileReader fr = new FileReader(".\\HelloWorld.txt");
FileWriter fw = new FileWriter(".\\sample.txt")) {
//read()メソッドの返り値を格納する変数を宣言します。
//read()メソッドの戻り値はint型なので、int型の変数を宣言します。
int chr;
//read()メソッドは読み取った文字をint型に変換して返し、ファイルの終わりに達した場合は-1を返します。
//そのため、fr.read()が-1を返すまでwhileループさせるとファイル全体を読み込むことができます。
while ((chr = fr.read()) != -1) {
//読み取った文字をコンソールに出力してみます。
//chrはint型の変数なので、char型にキャストすることで文字に直すことができます。
System.out.println((char) chr);
//読み取った文字をsample.txtに書き込みます。
fw.write(chr);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
FileWriterのコンストラクタに渡したパスに「sample.txt」というファイルが生成されます。実際に内容を確認すると、下記のようになっています。
Hello, World!
また、コンソールには以下のように出力されています。
H
e
l
l
o
,
W
o
r
l
d
!
文字ストリームから1文字ずつ読み込んでいることが確認できます。
BufferedReaderは、入力文字ストリームにバッファリング(バッファを利用した読み書きの効率化)の機能を追加するためのクラスです。バッファについては以下の記事で説明しています。
コンストラクタの引数には、Readerクラスを継承したクラス(FileReaderクラスなど)を取ります。
//コンストラクタにReaderクラスのサブクラスを渡します。
FileReader fr =new FileReader("ファイルのパス");
BufferedReader br = new BufferedReader(fr);
また、BufferedReaderには、行をまとめて読み込むためのreadLine()メソッドが追加されています。
メソッド名 | 返り値の型 | 説明 |
---|---|---|
readLine() | String | 入力文字ストリームから1行ずつ読み取ります。終端に達した場合はnullを返します。 |
BufferedWriterは、出力文字ストリームにバッファリングの機能を追加するためのクラスです。
コンストラクタの引数には、Writerクラスを継承したクラス(FileWriterクラスなど)を取ります。
//コンストラクタにWriterクラスのサブクラスを渡します。
FileWriter fw =new FileWriter("ファイルのパス");
BufferedWriter bw = new BufferedWriter(fr);
また、BufferedWriterには、改行文字を書き込むためのnewLine()メソッドが追加されています。
メソッド名 | 返り値の型 | 説明 |
---|---|---|
newLine() | void | 出力文字ストリームに改行文字を書き込みます。 |
以下のテキストファイル「IAmACat.txt」を例に、BufferedReader / BufferedWriterを使ったテキストファイルの読み込みと出力についての解説を行います。
吾輩は猫である。 名前はまだ無い。 どこで生れたかとんと見当がつかぬ。 何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
メモ帳などのワードエディタで上記内容を入力し、「IAmACat.txt」という名前で保存したテキストファイルを用意します。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class BufferedRWsample {
public static void main(String[] args) {
//読み込むファイルにIAmACat.txt、書き出すファイル名にsample2.txtを指定しています。
try (BufferedReader br = new BufferedReader(new FileReader(".\\IAmACat.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter(".\\Sample2.txt"))) {
//文字ストリームのテキスト行を格納するためのString型の変数lineを宣言します。
String line;
//readLine()メソッドは文字ストリームから1行ずつ読み込むことが出来ますが、
//終端に達したときにnullを返します。
//そのため、linebr.readLine()がnullを返すまでwhileループさせるとファイル全体を読み込むことが出来ます。
while ((line = br.readLine()) != null) {
//文字ストリームから読み込んだ内容を出力します。
System.out.println(line);
//読み込んだ内容を書き込みます。改行文字はreadLine()メソッドでは読み取らないので、
//改行を出力したい場合はnewLine()メソッドを使う必要があります。
bw.write(line);
bw.newLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
FileWriterのコンストラクタに渡したパスに新たに「sample2.txt」が出力されてことが確認できます。実際に「sample2.txt」の内容を確認すると、「IAmACat.txt」と同じ内容になっていることが確認できます。
また、コンソールには以下のように「IAmACat.txt」と同じ内容が出力されます。
吾輩は猫である。
名前はまだ無い。
どこで生れたかとんと見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
BufferedReader / BufferedWriterで使った「sample2.txt」を例に、Javaにおいてテキストファイルに追記する方法について説明します。
以下のコードで、「sample2.txt」に新たな行を追加します。
import java.io.BufferedWriter;
import java.io.FileWriter;
public class BufferedWriterAppendSample {
public static void main(String[] args) {
//FileWriterの第2引数にtrueを渡すことで、追記を行います。
try (BufferedWriter bw = new BufferedWriter(new FileWriter(".\\sample2.txt", true))) {
//追記する内容を記述します。改行を行うには、newLine()メソッドを使います。
bw.write("吾輩はここで始めて人間というものを見た。");
bw.newLine();
bw.write("しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。");
bw.newLine();
} catch (Exception e) {
e.printStackTrace();
}
}
}
このコードを実行した後に、「sample2.txt」の内容を確認すると、以下のような内容になっています。
吾輩は猫である。
名前はまだ無い。
どこで生れたかとんと見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。
sample2.txtに2行の文章が追加されたことが確認できます。
PrintWriterは、Java上でテキストファイルを出力する時に便利な、様々なメソッドを用意したクラスにです。
コンストラクタには、Writerを継承したクラスの他にも、OutputStreamを継承したクラスやFileクラス、パス名を表す文字列を渡すことが出来ます。
また、第二引数に文字コードを表す文字列を入れることで、文字コードの指定が出来ます。文字コードについては、以下の記事で解説しています。
//コンストラクタにWriteクラスのサブクラスを渡します。
FileWriter fw = new FileWriter("ファイルのパス");
PrintWriter pw = new PrintWriter(fw);
//コンストラクタにOutputStreamクラスのサブクラスを渡すことも出来ます。
FileOutputStream fos = new FileOutputStream("ファイルのパス");
PrintWriter pw = new PrintWriter(fos);
//コンストラクタに書き込むファイルのパスを直接指定することも出来ます。
PrintWriter pw = new PrintWriter("ファイルのパス");
//コンストラクタにFileオブジェクトを指定することも出来ます。
File file = new File("ファイルのパス");
PrintWriter pw = new PrintWriter(file);
//コンストラクタに文字コードを指定することで、書き込む際の文字コードを変更することが出来ます。
//WriterクラスやOutputStreamクラスを継承したクラスを渡したときは、
//文字コードは指定できませんので注意してください。
PrintWriter pw = new PrintWriter("ファイルのパス", "Unicode");
また、PrintWriterには、以下のようなメソッドが追加されています。
メソッド名 | 返り値の型 | 説明 |
---|---|---|
print(String s) | void | 出力ストリームに引数に渡した文字列sを書き込みます。 |
println(String s) | void | 出力ストリームに引数に渡した文字列sを書き込みます。最後に行の区切り文字を出力して、改行を行います。 |
printf(String format, Object... args) | PrintWriter | 書式指定子を含む文字列formatと、書式を指定して出力を行う、任意のオブジェクトからなる可変長引数argsを渡して指定した書式で書き込みます。 |
上記のうち、printメソッドとprintlnメソッドの引数には、String型の他に、int型やboolean型などのプリミティブ型、さらにはObject型を渡すことが出来ます。
printfメソッドは、System.out.printfメソッドと同様の書式指定子を使いますので、書式指定子に関する詳しい説明については、以下の記事を参照してください。
PrintWriterに用意された様々なメソッドを使って、テキストファイルに書き込みを行う方法を説明します。
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Date;
public class PrintWriterSample {
public static void main(String[] args) {
//PrintWriterのコンストラクタにBufferedWriterを渡すことで、書き込み時にバッファを利用できます。
try (PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(".\\sample4.txt")))){
//改行せずに文字列を書き込みます。
pw.print("Hello, ");
//改行して文字列を書き込みます。
pw.println("World!");
//boolean型やint型なども、変換を行うことなく直接書き込みを行うことが出来ます。
pw.println(true);
pw.println(123);
//書式指定子を使って、変数を文字列に含んだ状態で書き込みを行います。
//ここでは、%sに「25」が代入されます。
pw.printf("私の年齢は %s 才です。", 25);
pw.println();
//書式指定子を使って、浮動小数点の書き込み形式を指定します。
//ここでは、小数点以下第7桁を四捨五入して書き込みます。
double pi = 3.14159265;
pw.printf("円周率は %e です。", pi);
pw.println();
//書式指定子を使って、日時の書き込み形式を指定します。
//ここでは、Date()メソッドで現在の日時を取得して書き込みを行っています。
Date c = new Date();
pw.printf("現在の日時は %tY年 %tm月 %td日 %tH時 %tM分 %tS秒 です。", c, c, c, c, c, c);
pw.println();
} catch (Exception e) {
e.printStackTrace();
}
}
}
try-with-resources構文中のリソースが複雑なように感じますが、動作の中身としてはFileWriterクラスにBufferedWriterクラスのバッファリング機能を付け、さらにPrintWriterクラスの機能を付けるという構造になっています。ファイル出力の基本となるFileWriterクラスに、機能を追加していくイメージで考えればわかりやすいと思います。
このコードを実行した後に、「sample3.txt」の内容を確認すると、以下のような内容になっています。
Hello, World!
true
123
私の年齢は 25 才です。
円周率は 3.141593e+00 です。
現在の日時は 2020年 11月 26日 16時 33分 44秒 です。
PrintWriterのメソッドを使って様々な書式で出力が出来ることが確認できます。
InputStreamReader / OutputStreamWriterは、それぞれInputStreamからReader、OutputStreamからWriterの橋渡しをするためのクラスで、バイトストリームを文字ストリームに変換します。主にJava上でテキストファイルの文字コードを変換する際などに使われます。
InputStreamReader / OutputStreamWriterの使用例については、以下の記事で掲載しています。
inputStreamWriterは、指定した文字コードでバイトストリームから入力文字ストリームを読み込むためのクラスです。
コンストラクタの第一引数には、InputStreamクラスを継承したクラス(FileInputStreamクラスなど)を取り、第二引数には文字コードを表す文字列を取ります。
//コンストラクタの第一引数にInputStreamクラスのサブクラス、第二引数に文字コードを表す文字列渡します。
//第二引数を省略した場合は、デフォルトの文字コードを使用した入力文字ストリームを作成します。
FileInputStream fis =new FileInputStream("ファイルのパス");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
OutputStreamWriterは、指定した文字コードでバイトストリームから出力文字ストリームを書き出すためのクラスです。
コンストラクタの引数には、OutputStreamクラスを継承したクラス(FileOutputStreamクラスなど)を取り、第二引数には文字コードを表す文字列を取ります。
//コンストラクタの第一引数にOutputStreamクラスのサブクラス、第二引数に文字コードを表す文字列渡します。
//第二引数を省略した場合は、デフォルトの文字コードを使用した出力文字ストリームを作成します。
FileOutputStream fos =new FileOutputStream("ファイルのパス");
OutputStreamReader osr = new OutputStreamReader(fos, "UTF-8");
今回はJavaにおけるテキストファイルの読み込みと出力についての説明を行いました。様々なクラスがありますが、FileReader/FileWriterを基本として、それを拡張するという考え方をすればわかりやすいと思います。Javaを扱う実務でもログファイルの出力など、頻繁に使う機会があるので、その際に当記事が参考になれば幸いです。
関連記事:
【Java】try - with - resources 構文
【著者】
フォワードソフト株式会社のエンジニア。Java、Python、JavaScript、C#などの言語の他、クラウドやネットワーク技術を勉強しています。PythonやVBAを使った自動化で楽をする方法を考えるのが好きです。 最近はジェネレーティブAIの業務利用に関する検証を行っています。 資格を通じて知識を吸収することを心がけており、セキュリティスペシャリスト、データベーススペシャリスト、応用情報技術者、Oracle Certified Java Programmer Gold SE 11、Pythin3 エンジニア認定試験、HTML5プロフェッショナル認定試験レベル2、AWSプラクティショナーなどの情報資格を保有しています。
そのような方はぜひ、Workteriaサイトをご利用ください!
定期的にご本人に合う高額案件を紹介
リモートワークなど自由な働き方ができる案件多数
専属エージェントが契約や請求をトータルサポート
こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ
こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ
こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo
こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS
こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様