質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

1587閲覧

CSVファイルを固定長のテキストファイルに出力したい

moo1211

総合スコア3

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

0クリップ

投稿2023/04/24 02:39

編集2023/04/24 05:11

前提・ 実現したいこと

【実現したいこと一覧】
①全角文字項目は値の後ろに、全角スペース埋めをしたい
②テキストファイルに1レコード書き込みごとに改行したい

③半角文字項目は値の後ろに、半角スペース埋めをしたい(すでに実装済み)
④ダブルコーテーションがあったら、削除してテキストファイルに書き込みたい(すでに実装済み?)
⑤数値項目は値の前に、0埋めをしたい(すでに実装済み)

【変換前CSVファイル】※全角スペースは□で表現しています。 B,2023,1,22,1,1234567,12345,"山田たろう□□□□□□□□□□□" B,2023,1,22,1,123456,1234,"佐藤けん□□□□"

上記のようなCSVファイルをJavaで読み込み、テキストファイルに変換するプログラムを作っています。

【変換後テキストファイル】※全角スペースは□で表現しています。 B2023012211234567000012345山田たろう□□□□□□□□□□□ B2023012210123456000001234佐藤けん□□□□□□□□□□□□

↓こちらの質問を参考にソースを作成しております。
https://teratail.com/questions/329018
それぞれ(1バイト,4バイト,2バイト,2バイト,1バイト,7バイト,9バイト,32バイト(全角16文字))の固定長で変換したいと思っています。

データ例(全角文字項目):
変換前:"佐藤けん□□□□"
変換後:佐藤けん□□□□□□□□□□□□(32バイト)
※全角スペースは□で表現しています。また、半角全角混合のパターンは無いと想定しています。

発生している問題・エラーメッセージ

csvデータ1レコード目(山田たろうのデータ)は出力できるのですが、2レコード目(佐藤けんのデータ)が出力できません。
二つのデータ間で何が違くて出力結果に差があるのかが知りたいです。
また、改行をするよう「16s\n」のように書いているつもりなのですが、こちらも問題の原因がわかりません。

【プログラム実行後出力ファイル】 B2023012211234567000012345山田たろう           B2023012210123456000001234
【エラーメッセージ】 java.lang.IndexOutOfBoundsException at java.base/java.io.FileOutputStream.writeBytes(Native Method) at java.base/java.io.FileOutputStream.write(FileOutputStream.java:373) at CsvToText10.main(CsvToText10.java:36) 異常終了しました。

該当のソースコード

Java

1//package jp.aast.kyoiku; 2import java.io.*; 3 4 5public class CsvToText10 { 6 7 public static void main(final String args[]) { 8 try ( 9 BufferedReader reader = new BufferedReader(new InputStreamReader( 10 new FileInputStream(args[0]), "Windows-31J")); 11 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( 12 new FileOutputStream(args[1]), "Windows-31J"))) { 13 14 final FileOutputStream os = new FileOutputStream(args[1]); 15 while (reader.ready()) { 16 //入力ファイルから1行読み込む。 17 final String line = reader.readLine(); 18 19 20 final String enc = "Windows-31J"; 21 22 final String[] items = line.replace("\"", "").split(","); 23 //行データを出力ファイルへ書き出す。 24 os.write(String.format("%-100s", items[0]).getBytes(enc), 0, 1); 25 os.write(String.format("%04d", Integer.parseInt(items[1])).getBytes(enc)); 26 os.write(String.format("%02d", Integer.parseInt(items[2])).getBytes(enc)); 27 os.write(String.format("%02d", Integer.parseInt(items[3])).getBytes(enc)); 28 os.write(String.format("%01d", Integer.parseInt(items[4])).getBytes(enc)); 29 os.write(String.format("%07d", Integer.parseInt(items[5])).getBytes(enc)); 30 os.write(String.format("%09d", Integer.parseInt(items[6])).getBytes(enc)); 31 32 //修正したい箇所 33 //①半角スペースではなく全角スペースにしたい 34 //②改行したい 35 os.write(String.format("%.16s\n", items[7]).getBytes(enc), 0, 32); 36 //os.write(String.format(" ", items[7]).getBytes(enc), 0, 32); 37 //os.write("\n".getBytes(enc)); 38 39 40 } 41 os.close(); 42 43 } catch (Exception e) { 44 e.printStackTrace(); 45 46 System.out.println("異常終了しました。"); 47 System.exit(-1); 48 } 49 50 System.out.println("正常終了しました。"); 51 System.exit(0); 52 53 } 54 55} 56 57

考えをまとめ切れておらず、わかりづらい質問となってしまい申し訳ありませんが、問題の一部分についてのみでもいいのでご回答いただけると幸いです。

お忙しいところ恐縮ですがよろしくお願いいたします。

neko_the_shadow👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2023/04/24 03:19

多バイト文字はかならずしも2バイトとはかぎりません。3バイト文字が発生した時点で全角スペースでうめても固定長にすることは難しいのでは?
moo1211

2023/04/24 03:45

コメントいただきありがとうございます! 入力データの時点で全角文字項目は全角文字(1文字2バイト)のみの想定で、奇数バイト(3バイト文字の発生や、2バイト文字+1バイト文字の組み合わせ)のパターンは想定しないで大丈夫だと考えております。
jimbe

2023/04/24 09:54 編集

まず、何が原因でエラーをなっているのかを調査してください。 IndexOutOfBoundsException は配列で添え字の値が範囲外だった場合に主に発生します。 発生個所は CsvToText10.java ファイルの 36 行目です。 例えばその行で扱っている配列の大きさと添え字の変数の値をその行の前で表示してみては如何でしょうか。 そして、ほぼ質問内容が前と同じです。(現象が違うと言われるかと思いますが、僅かに進捗?があった程度の違いです。) この程度なら前の質問を追加/修正されたほうが分かり易いと思います。
moo1211

2023/04/25 00:59

jimbe様 またまたご回答いただきありがとうございます! すみません、配列とか変数の中身の値を表示してみるという考え方がなかったのでこの後実験してみます! また、質問内容について似たような内容となってしまい申し訳ございません。 以後気を付けるようにいたします。 前回質問のjimbe様にいただいたソースについて質問させていただきたいことがあり、今日中に投稿予定なのでお時間ある時にご回答いただけますと幸いです。
guest

回答3

0

PrintWriter の printf を使えば簡単です。

Java

1import java.io.*; 2 3public class CsvToText10 { 4 public static void main(final String args[]) { 5 try ( 6 BufferedReader reader = new BufferedReader( 7 new InputStreamReader( 8 new FileInputStream(args[0]), "Windows-31J")); 9 PrintWriter writer = new PrintWriter( 10 new BufferedWriter( 11 new OutputStreamWriter( 12 new FileOutputStream(args[1]), "Windows-31J"))) 13 ) { 14 String line; 15 while ((line = reader.readLine()) != null) { 16 final String[] s = line.replace("\"", "").split(","); 17 writer.printf("%s%04d%02d%02d%01d%07d%09d%.16s%n", 18 s[0], pi(s[1]), pi(s[2]), pi(s[3]), pi(s[4]), pi(s[5]), 19 pi(s[6]), s[7] + "□□□□□□□□□□□□□□□"); 20 } 21 writer.close(); 22 } catch (Exception e) { 23 e.printStackTrace(); 24 System.out.println("異常終了しました。"); 25 System.exit(-1); 26 } 27 System.out.println("正常終了しました。"); 28 System.exit(0); 29 } 30 31 static int pi(String s) { return Integer.parseInt(s); } // ParseInt 32}

"□□□□□□□□□□□□□□□" は全角スペース列に書き換えてください。

投稿2023/04/26 09:35

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moo1211

2023/05/01 01:15

kazuma-s様 ご回答いただきありがとうございます! こちら作成したい機能を無事に作ることができました! 大変勉強になりました、ありがとうございます!
guest

0

ベストアンサー

ファイルへの書き出しにあたって、BufferedWriter writerFileOutputStream osの両方を利用されていますが、SJISのファイルを書き出したいのであれば、後者は不要です。FileOutputStream osに関係するコードはすべて削除してよいでしょう。

CSVファイルを1行ずつ読み込みながら、固定長のデータに変換し、ファイルへ書き出す部分ですが、以下のように実装するとよいと思います。

java

1String line; 2while ((line = reader.readLine()) != null) { 3 String[] items = line.replace("\"", "").split(","); 4 5 //行データを出力ファイルへ書き出す。 6 writer.write(items[0]); 7 writer.write(String.format("%04d", Integer.parseInt(items[1]))); 8 writer.write(String.format("%02d", Integer.parseInt(items[2]))); 9 writer.write(String.format("%02d", Integer.parseInt(items[3]))); 10 writer.write(String.format("%01d", Integer.parseInt(items[4]))); 11 writer.write(String.format("%07d", Integer.parseInt(items[5]))); 12 writer.write(String.format("%09d", Integer.parseInt(items[6]))); 13 writer.write(items[7] + " ".repeat(32-items[7].length()) + "\n"); 14}

投稿2023/04/24 13:29

neko_the_shadow

総合スコア2349

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moo1211

2023/04/25 01:05

neko_the_shadow様 ご回答いただきありがとうございます! 自分がしっかり理解できていなくて複雑になっていた部分が、いただいたソースだとすっきりしている気がします! 自分で実行して、挙動を確認してみようと思います! ありがとうございます!
shiketa

2023/04/25 01:31

細かいことですが。こうかと。 > neko_the_shadowさん ```diff - writer.write(items[7] + " ".repeat(32-items[7].length()) + "\n"); + writer.write(items[7] + " ".repeat(16-items[7].length()) + "\n"); ```
moo1211

2023/05/01 01:12

お二人ともありがとうございます! こちら作りたい機能が実現できました!
guest

0

java.lang.IndexOutOfBoundsExceptionと言われているのだから、元の文字数が足りていないわけでしょ?だったら不足しないように足してやればいい。

java

1os.write( 2( 3items[7] + 4"\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000" 5).getBytes(enc), 0, 32 6);

neko_the_shadowさんの回答を参考にして。こうでも。

java

1os.write((tems[7] + "\u3000".repeat(16)).getBytes(enc), 0, 32);

投稿2023/04/24 05:38

編集2023/04/25 01:34
shiketa

総合スコア4061

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moo1211

2023/04/25 00:55

shiketa様 またまたご回答いただきありがとうございます! いただいたソースに修正して実行してみます!
moo1211

2023/05/01 01:15

shiketa様 ご回答いただきありがとうございます! こちら作成したい機能を無事に作ることができました! 大変勉強になりました、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問