challenge 固定長データ

固定長のデータが記載されたファイルを読み込むプログラムを作成してください。読み込んだデータは、複数の値を格納できるデータ型に格納してください。

ファイルには、すべて ascii 文字で以下のデータが格納されています。デリミタはなく、固定長で格納されています。レコードとレコードのあいだも改行はありません。

  1. 姓 (12文字) 文字数が足りない場合は、後ろを空白で埋めてあります。
  2. 名 (12文字) 文字数が足りない場合は、後ろを空白で埋めてあります。
  3. 性別 (F,M,Uの3種類、1文字)
  4. 年齢 (3桁の数字、桁数が足りない場合は、ゼロで埋めず、頭を空白で埋めてあります。
  5. 年 2008 固定
  6. 月 03 固定
  7. さらに以下のデータが日付分くりかえされます。
    1. 日付 (01 〜 31) 2文字
    2. 朝食のメニュー (500文字)
    3. 昼食のメニュー (500文字)
    4. 夕食のメニュー (500文字)

以上の形式のデータ500人分を読みこんで、データを複数の値を格納できるデータ型に格納してください。データに大して何か処理を行う必要はなく、すぐに破棄してかまいません。

この問題は、このようなファイルをどのように扱うかを知りたくて作成しました。

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));
        }
    }
}

Index

Feed

Other

Link

Pathtraq

loading...