固定長データ
Posted feedbacks - Java
とりあえず、こんな感じで。 ちゃんとやるなら、ReadとWriteの処理はRecordとセットのクラスを用意するかも。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Sample170 {
private static final String encoding = "MS932";
private static final String FILE_NAME = "record.dat";
public static void main(String[] args) {
try {
createTestData(FILE_NAME);
List<Record> records = readData(FILE_NAME);
System.out.println(records.size());
} catch (IOException e) {
e.printStackTrace();
}
}
private static List<Record> readData(String fileName) throws IOException {
Reader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), encoding));
List<Record> result = new ArrayList<Record>();
char[] smallBuf = new char[12];
char[] menuBuf = new char[500];
while (true) {
Record record = new Record();
if (reader.read(smallBuf) < 0) break;
record.familyName = String.valueOf(smallBuf).trim();
if (reader.read(smallBuf) < 0) break;
record.firstName = String.valueOf(smallBuf).trim();
if (reader.read(smallBuf, 0 , 1) < 0) break;
record.sex = Record.Sex.valueOf(String.valueOf(smallBuf[0]));
if (reader.read(smallBuf, 0 , 3) < 0) break;
record.age = Integer.parseInt(String.valueOf(smallBuf, 0, 3).trim());
if (reader.read(smallBuf, 0 , 4) < 0) break;
int year = Integer.parseInt(String.valueOf(smallBuf, 0, 4).trim());
if (reader.read(smallBuf, 0 , 2) < 0) break;
int month = Integer.parseInt(String.valueOf(smallBuf, 0, 2).trim());
for (int index = 1; index <= 31; index++) {
MenuData menu = new MenuData();
menu.year = year;
menu.month = month;
if (reader.read(smallBuf, 0 , 2) < 0) break;
menu.day = Integer.parseInt(String.valueOf(smallBuf, 0, 2).trim());
if (reader.read(menuBuf) < 0) break;
menu.breakfast = String.valueOf(menuBuf).trim();
if (reader.read(menuBuf) < 0) break;
menu.lunch = String.valueOf(menuBuf).trim();
if (reader.read(menuBuf) < 0) break;
menu.dinner = String.valueOf(menuBuf).trim();
}
result.add(record);
}
return result;
} finally {
if (reader != null) {
reader.close();
}
}
}
private static void createTestData(String fileName) throws IOException {
Writer writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), encoding));
Random random = new Random();
Record.Sex[] sexValues = Record.Sex.values();
for (int index = 0; index < 500; index++) {
writer.write(String.format("%-12s", "FamilyName"));
writer.write(String.format("%-12s", "FirstName"));
writer.write(sexValues[random.nextInt(sexValues.length)].toString());
writer.write(String.format("%3d", random.nextInt(120)));
writer.write("2008");
writer.write("03");
for (int day = 1; day <= 31; day++) {
writer.write(String.format("%02d", day));
writer.write(String.format("%-500s", "breakfast menu."));
writer.write(String.format("%-500s", "lunch menu."));
writer.write(String.format("%-500s", "dinner menu."));
}
}
} finally {
if (writer != null) {
writer.close();
}
}
}
}
class Record {
public enum Sex {
F, M, U,
}
public String familyName;
public String firstName;
public Sex sex;
public int age;
public final List<MenuData> menuList = new ArrayList<MenuData>();
}
class MenuData {
public int year;
public int month;
public int day;
public String breakfast;
public String lunch;
public String dinner;
}
|
固定長で読み込むReaderを実装するアプローチです。文字数ではなく「バイト数」で読むようにしています(Readerを継承させる意味はあまりなかったかもしれません)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import java.io.*;
import java.util.*;
public class FixedReader extends Reader {
public static final File inputFile = new File("test.ascii");
private InputStream inStream;
private String encoding;
public FixedReader(InputStream in, String encoding) {
this.inStream = in;
this.encoding = encoding;
}
public String read(int length) throws IOException {
byte[] buff = new byte[length];
if (inStream.read(buff) < length)
throw new EOFException();
return new String(buff, encoding).trim();
}
public int read(char[] buf, int offset, int length) throws IOException {
String str = read(length);
str.getChars(0, str.length(), buf, offset);
return str.length();
}
public void close() throws IOException {
inStream.close();
}
public static void main(String[] args) throws IOException {
FixedReader fr = new FixedReader(new FileInputStream(inputFile), "US-ASCII");
LinkedHashMap<String, Map<String, Object>> ml = new LinkedHashMap<String, Map<String, Object>>();
for (int i = 0; i < 500; i++) {
Map<String, Object> m = new LinkedHashMap<String, Object>();
m.put("姓", fr.read(12));
m.put("名", fr.read(12));
m.put("性別", fr.read(1));
m.put("年齢", fr.read(3));
m.put("年", fr.read(4));
m.put("月", fr.read(2));
LinkedHashMap<String, Map<String, String>> l = new LinkedHashMap<String, Map<String, String>>(31);
for (int j = 0; j < 31; j++) {
Map<String, String> m2 = new LinkedHashMap<String, String>();
m2.put("日付", fr.read(2));
m2.put("朝食", fr.read(500));
m2.put("昼食", fr.read(500));
m2.put("夕食", fr.read(500));
l.put(m2.get("日付"), m2);
}
m.put("日毎", l);
ml.put(m.get("姓") + " " + m.get("名"), m);
}
fr.close();
for (String key : ml.keySet()) {
System.out.println(ml.get(key));
}
}
}
|


Mymelo #6060() Rating5/7=0.71
固定長のデータが記載されたファイルを読み込むプログラムを作成してください。読み込んだデータは、複数の値を格納できるデータ型に格納してください。
ファイルには、すべて ascii 文字で以下のデータが格納されています。デリミタはなく、固定長で格納されています。レコードとレコードのあいだも改行はありません。
以上の形式のデータ500人分を読みこんで、データを複数の値を格納できるデータ型に格納してください。データに大して何か処理を行う必要はなく、すぐに破棄してかまいません。
この問題は、このようなファイルをどのように扱うかを知りたくて作成しました。
[ reply ]