Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.file / org.gvsig.fmap.dal.file.csv / src / main / java / org / gvsig / fmap / dal / store / csv / csvlib / TextFileAsList.java @ 45721

History | View | Annotate | Download (6.41 KB)

1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.fmap.dal.store.csv.csvlib;
7

    
8
import java.io.Closeable;
9
import java.io.DataOutputStream;
10
import java.io.File;
11
import java.io.FileOutputStream;
12
import java.io.IOException;
13
import java.io.RandomAccessFile;
14
import java.nio.LongBuffer;
15
import java.nio.MappedByteBuffer;
16
import java.nio.channels.FileChannel.MapMode;
17
import java.nio.charset.Charset;
18
import java.util.AbstractList;
19
import java.util.Arrays;
20
import java.util.Date;
21
import java.util.List;
22
import org.apache.commons.io.FilenameUtils;
23
import org.apache.commons.io.IOUtils;
24

    
25
/**
26
 *
27
 * @author jjdelcerro
28
 */
29
public class TextFileAsList extends AbstractList<String> implements Closeable {
30

    
31
    private final File text;
32
    private final File idx;
33
    private final Charset charset;
34
    private final Bytes buffer;
35

    
36
    private RandomAccessFile text_raf;
37

    
38
    private RandomAccessFile idx_raf;
39
    private MappedByteBuffer idx_map;
40
    private LongBuffer idx_buffer;
41

    
42
    public TextFileAsList(File text, File idx, Charset charset) {
43
        this.text = text;
44
        this.idx = idx;
45
        this.charset = charset;
46
        this.buffer = new Bytes(this.charset);
47
    }
48

    
49
    public static void create_index(File csv, File idx, Charset charset) throws IOException {
50
        FileOutputStream idx_fos = null;
51
        DataOutputStream idx_dos = null;
52
        RandomAccessFile csv_raf = null;
53
        try {
54
            idx_fos = new FileOutputStream(idx);
55
            idx_dos = new DataOutputStream(idx_fos);
56
            csv_raf = new RandomAccessFile(csv, "r");
57
            Bytes buffer = new Bytes(charset);
58
            String line;
59
            long pos = csv_raf.getFilePointer();
60
            while ((line = readLine(csv_raf, buffer)) != null) {
61
                idx_dos.writeLong(pos);
62
                pos = csv_raf.getFilePointer();
63
            }
64
        } finally {
65
            IOUtils.closeQuietly(idx_dos);
66
            IOUtils.closeQuietly(idx_fos);
67
            IOUtils.closeQuietly(csv_raf);
68
        }
69
    }
70

    
71
    public void open() {
72
        try {
73
            text_raf = new RandomAccessFile(this.text, "r");
74
            idx_raf = new RandomAccessFile(this.idx, "r");
75
            long idx_size = idx_raf.length();
76
            idx_map = idx_raf.getChannel().map(MapMode.READ_ONLY, 0, idx_size);
77
            idx_buffer = idx_map.asLongBuffer();
78
        } catch (IOException ex) {
79
            throw new RuntimeException("Can't open csv/idx files.", ex);
80
        }
81
    }
82

    
83
    private long getFilePointer(int lineno) {
84
        if (idx_buffer == null) {
85
            this.open();
86
        }
87
        return idx_buffer.get(lineno);
88
    }
89

    
90
    @Override
91
    public void close() {
92
        IOUtils.closeQuietly(this.text_raf);
93
        IOUtils.closeQuietly(this.idx_raf);
94
        this.idx_buffer = null;
95
        this.idx_map = null;
96
    }
97

    
98
    @Override
99
    public String get(int index) {
100
        if (text_raf == null) {
101
            this.open();
102
        }
103
        try {
104
            long pos = this.getFilePointer(index);
105
            this.text_raf.seek(pos);
106
            return readLine(text_raf, this.buffer);
107
        } catch (IOException ex) {
108
            throw new RuntimeException("Can't access to " + index + " element.", ex);
109
        }
110
    }
111

    
112
    @Override
113
    public int size() {
114
        if (idx_buffer == null) {
115
            this.open();
116
        }
117
        return this.idx_buffer.capacity();
118
    }
119

    
120
    @Override
121
    public void clear() {
122
        throw new UnsupportedOperationException();
123
    }
124

    
125
    private static class Bytes {
126

    
127
        private static final int DEFAULT_CAPACITY = 1024;
128
        private final Charset charset;
129

    
130
        private byte[] buffer = new byte[DEFAULT_CAPACITY];
131
        private int pos = 0;
132

    
133
        public Bytes(Charset charset) {
134
            this.charset = charset;
135
        }
136

    
137
        public void reset() {
138
            this.pos = 0;
139
        }
140

    
141
        public void append(int value) {
142
            if (pos >= buffer.length) {
143
                grow(buffer.length + DEFAULT_CAPACITY);
144
            }
145
            this.buffer[pos++] = (byte) value;
146
        }
147

    
148
        private void grow(int minCapacity) {
149
            buffer = Arrays.copyOf(buffer, minCapacity);
150
        }
151

    
152
        public int length() {
153
            return this.pos;
154
        }
155

    
156
        @Override
157
        public String toString() {
158
            String s = new String(buffer, 0, pos, charset);
159
            return s;
160
        }
161
    }
162

    
163
    private static String readLine(RandomAccessFile raf, Bytes buffer) throws IOException {
164
        buffer.reset();
165
        int c = -1;
166
        boolean eol = false;
167

    
168
        while (!eol) {
169
            switch (c = raf.read()) {
170
                case -1:
171
                case '\n':
172
                    eol = true;
173
                    break;
174
                case '\r':
175
                    eol = true;
176
                    long cur = raf.getFilePointer();
177
                    if ((raf.read()) != '\n') {
178
                        raf.seek(cur);
179
                    }
180
                    break;
181
                default:
182
                    buffer.append(c);
183
                    break;
184
            }
185
        }
186

    
187
        if ((c == -1) && (buffer.length() == 0)) {
188
            return null;
189
        }
190
        return buffer.toString();
191
    }
192

    
193
    public static void main(String[] args) throws Exception {
194
        String fname;
195
//        fname = "/home/jjdelcerro/Descargas/test/origen_coordenadas.csv";
196
//        fname = "/home/jjdelcerro/Descargas/test/esp_poblaciones.csv";
197
        fname = "/home/jjdelcerro/Descargas/test/esp_provincias.csv";
198

    
199
        File csv_file = new File(fname);
200
        File idx_file = new File(FilenameUtils.removeExtension(csv_file.getAbsolutePath()) + ".idx");
201

    
202
        TextFileAsList.create_index(csv_file, idx_file, Charset.forName("UTF-8"));
203

    
204
        List<String> text = new TextFileAsList(csv_file, idx_file, Charset.forName("UTF-8"));
205
        System.out.println("Lines " + text.size());
206
        for (String line : text) {
207
//            System.out.println(line);
208
        }
209
//        System.out.println("-----------------");
210
        long t1 = new Date().getTime();
211
        for (int i = text.size()-1; i >= 0 ; i--) {
212
            String line = text.get(i);
213
//            System.out.println(String.format("%6d: %s", i, line));
214
        }
215
        long t2 = new Date().getTime();
216
        System.out.println("Time: "+ (t2-t1) + " ms");
217
        IOUtils.closeQuietly((Closeable) text);
218
    }
219

    
220
}