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 / simplereaders / CSVReaderSuperCSV.java @ 47638

History | View | Annotate | Download (9.83 KB)

1
package org.gvsig.fmap.dal.store.csv.simplereaders;
2

    
3
import java.io.BufferedReader;
4
import java.io.File;
5
import java.io.IOException;
6
import java.io.Reader;
7
import java.util.List;
8
import java.util.function.Function;
9
import org.apache.commons.io.FilenameUtils;
10
import org.apache.commons.io.input.CloseShieldReader;
11
import org.apache.commons.lang3.StringUtils;
12
import org.apache.commons.text.StringEscapeUtils;
13
import org.gvsig.fmap.dal.store.csv.CSVStoreParameters;
14
import org.gvsig.fmap.dal.store.simplereader.virtualrows.RandomAccessFileIndex;
15
import org.gvsig.fmap.dal.store.simplereader.virtualrows.RandomAccessFileReader;
16
import static org.gvsig.fmap.dal.store.simplereader.virtualrows.RandomAccessFileReader.FILTER_NONE;
17
import org.gvsig.fmap.dal.store.csv.virtualrows.SuperCSVList;
18
import org.gvsig.fmap.dal.store.simplereader.simplereaders.AbstractSimpleReader;
19
import org.gvsig.tools.dynobject.DynObject;
20
import org.gvsig.tools.task.SimpleTaskStatus;
21
import org.gvsig.tools.util.GetItemWithSize64;
22
import org.slf4j.Logger;
23
import org.slf4j.LoggerFactory;
24
import org.supercsv.comment.CommentStartsWith;
25
import org.supercsv.io.CsvListReader;
26
import org.supercsv.prefs.CsvPreference;
27
import org.supercsv.quote.QuoteMode;
28

    
29
public class CSVReaderSuperCSV extends AbstractSimpleReader {
30

    
31
    //
32
    // http://supercsv.sourceforge.net/examples_reading.html
33
    // http://supercsv.sourceforge.net/apidocs/index.html
34
    //
35
    private static final Logger LOGGER = LoggerFactory.getLogger(CSVReaderSuperCSV.class);
36

    
37
    private CsvListReader reader;
38
    private final CSVStoreParameters parameters;
39
    private List<String>  nextLine;
40
    private int columns;
41

    
42
    public CSVReaderSuperCSV(Reader in, CSVStoreParameters parameters) {
43
        this(parameters);
44
        this.reader = new CsvListReader(in, getCSVPreferences());
45
    }    
46
    
47
    public CSVReaderSuperCSV(CSVStoreParameters parameters) {
48
        this.reader = null;
49
        this.parameters = parameters;
50
        this.reader = null;
51
        this.nextLine = null;
52
        this.columns = 0;
53
    }
54

    
55
    public CSVStoreParameters getParameters() {
56
        return this.parameters;
57
    }
58

    
59
    @Override
60
    public String[] getHeader() throws IOException {
61
        return this.reader.getHeader(true);
62
    }
63
    
64
    @Override
65
    public int getColumnsCount() throws IOException {
66
        if( this.columns <= 0 ) {
67
            this.columns = reader.length();
68
            if( this.columns <= 0 ) {
69
                this.nextLine = this.reader.read();
70
                this.columns = reader.length();
71
            }
72
        }
73
        return this.columns;
74
    }
75

    
76
    @Override
77
    public GetItemWithSize64<List<String>>  getVirtualRows(SimpleTaskStatus status) {
78
        RandomAccessFileReader theReader = null;
79
        RandomAccessFileIndex theIndex = null;
80
        try {
81
            CSVStoreParameters params = getParameters();
82
            File data_file = CSVStoreParameters.getFile(params);
83
            if( data_file.length()< 10*1024*1024 ) {
84
                return null;
85
            }
86
            
87
            Function<BufferedReader, Integer> numberOfLinesInRecord = new Function<BufferedReader, Integer>() {
88
                @Override
89
                public Integer apply(BufferedReader breader) {
90
                    CloseShieldReader theReader = CloseShieldReader.wrap(breader);
91
                    CsvListReader parser = new CsvListReader(theReader, getCSVPreferences());
92
                    try {
93
                        List<String> values = parser.read();
94
                    } catch (IOException ex) {
95
                        return 1;
96
                    }
97
                    return parser.getLineNumber();
98
                }
99
            };
100

    
101
            String charset = CSVStoreParameters.getCharset(params);
102
            File index_file = getIndexFile(data_file);
103
            
104
            theReader = new RandomAccessFileReader(data_file, charset);
105
            theIndex = theReader.createOrOpenIndexOfLines(index_file, false, FILTER_NONE, status, numberOfLinesInRecord);
106
            
107
            SuperCSVList list = new SuperCSVList(
108
                    theReader, 
109
                    theIndex, 
110
                    CSVStoreParameters.isFirstLineHeader(getParameters())?1:0
111
            );
112
            
113
            list.setPreferences(this.getCSVPreferences());
114
            return list;
115
        } catch (IOException ex) {
116
            return null;
117
        } finally {
118
            // We do not close the index or the reader because we need it to remain open
119
//            IOUtils.closeQuietly(theReader);
120
//            IOUtils.closeQuietly(theIndex);
121
        }
122
    }
123
    
124
    @Override
125
    public List<String> read() throws IOException {
126
        List<String> line;
127
        if( this.nextLine != null ) {
128
            line = this.nextLine;
129
            this.nextLine = null;
130
        } else {
131
            line = this.reader.read();
132
        }
133
        if( line!=null ) {
134
            for (int i = 0; i < line.size(); i++) {
135
                String s = line.get(i);
136
                if( s!=null ) {
137
                    line.set(i, unescapeCRLF(s));
138
                }
139
            }
140
        }
141
        return line;
142
    }
143

    
144
    @Override
145
    public void close() throws IOException {
146
        this.reader.close();
147
    }
148

    
149
    @Override
150
    public List<String> skip(int lines) throws IOException {
151
        if( lines <= 0 ) {
152
            return null;
153
        }
154
        if( this.nextLine != null ) {
155
            this.nextLine = null;
156
            lines--;
157
        }
158
        List<String> row = null;
159
        for ( int i = 0; i < lines; i++ ) {
160
            row = reader.read();
161
        }
162
        return row;
163
    }
164

    
165
    public final CsvPreference getCSVPreferences() {
166
        try {
167
            String s;
168
            char quoteChar;
169
            int delimiterChar;
170
            String endOfLineSymbols;
171

    
172
            DynObject params = this.getParameters();
173

    
174
            CsvPreference.Builder builder;
175

    
176
            CsvPreference defaultPreference = CSVStoreParameters
177
                    .getPredefinedCSVPreferences(params);
178
            if ( defaultPreference == null ) {
179
                defaultPreference = CsvPreference.STANDARD_PREFERENCE;
180
            }
181

    
182
            endOfLineSymbols = CSVStoreParameters.getRecordSeparator(params);
183
            if ( StringUtils.isBlank(endOfLineSymbols) ) {
184
                endOfLineSymbols = defaultPreference.getEndOfLineSymbols();
185
            }
186
            s = CSVStoreParameters.getQuoteCharacter(params);
187
            if ( StringUtils.isBlank(s) ) {
188
                quoteChar = (char) defaultPreference.getQuoteChar();
189
            } else {
190
                quoteChar = s.charAt(0);
191
            }
192
            s = CSVStoreParameters.getDelimiter(params);
193
            if ( StringUtils.isBlank(s) ) {
194
                delimiterChar = defaultPreference.getDelimiterChar();
195
            } else {
196
                delimiterChar = s.charAt(0);
197
            }
198

    
199
            builder = new CsvPreference.Builder(quoteChar, delimiterChar,
200
                    endOfLineSymbols);
201

    
202
            s = CSVStoreParameters.getCommentStartMarker(params);
203
            if ( !StringUtils.isBlank(s) ) {
204
                CommentStartsWith cs = new CommentStartsWith(s);
205
                builder.skipComments(cs);
206
            }
207

    
208
            builder.surroundingSpacesNeedQuotes(CSVStoreParameters
209
                    .getSurroundingSpacesNeedQuotes(params));
210
            QuoteMode quoteMode = CSVStoreParameters.getQuoteMode(params);
211
            if ( quoteMode != null ) {
212
                builder.useQuoteMode(quoteMode);
213
            }
214
            return builder.build();
215
        } catch (Exception e) {
216
            LOGGER.warn("Can't make preferences for CSV '" + getFullFileName()
217
                    + "'.", e);
218
            return null;
219
        }
220
    }
221
    
222
    private String getFullFileName() {
223
        // Usar solo para mostrar mensajes en el logger.
224
        String s;
225
        try {
226
            s = getParameters().getFile().getAbsolutePath();
227
        } catch (Exception e2) {
228
            s = "(unknow)";
229
        }
230
        return s;        
231
    }
232

    
233
    @Override
234
    public int getLine() {
235
        if( this.reader==null ) {
236
            return 0;
237
        }
238
        return this.reader.getLineNumber();
239
    }
240

    
241
    @Override
242
    public List<String> nextRowValues() {
243
        try {
244
            return this.read();
245
        } catch (IOException ex) {
246
            throw new RuntimeException(ex);
247
        }
248
    }
249

    
250
    public static String escapeCRLF(String s) {
251
        if( s==null ) {
252
            return s;
253
        }
254
        String s1 = s;
255
        s1 = StringUtils.replace(s1, "\\", "\\\\");
256
        s1 = StringUtils.replace(s1, "\n", "\\n");
257
        s1 = StringUtils.replace(s1, "\r", "\\r");
258
        return s1;
259
    }
260
    
261
    public static String unescapeCRLF(String s) {
262
        if( s==null || s.indexOf('\\')==-1 ) {
263
            return s;
264
        }
265
        String s1 = s;
266
        s1 = s.replaceAll("(?:^\\\\n)|(?:([^\\\\])\\\\n)","$1\n");
267
        s1 = s1.replaceAll("(?:^\\\\r)|(?:([^\\\\])\\\\n)","$1\r");
268
        s1 = StringUtils.replace(s1, "\\\\", "\\");
269
        return s1;
270
    }
271
    
272
    
273
    public static void main(String[] args) {
274
        String s0 = "\\n{\\n   \"ANGULO\":\"0.000\",\\n    \"\tEXTO\":\"RAVAL ROIG\\\\r\\\\n - \\\\r\\\\nVIRGEN DEL SOCORRO\",\\n    \"LINK_POLIGONO\":\"HVCSGISCODE_ENT_11230100000000001\",\\n    \"GEOMETRY\":\"00000000014125fe9b57b4a23441503411cb1c432d\"\\n}";
275
        System.out.println("#"+s0+"#");
276
        String s1 = s0.replaceAll("(?:^\\\\n)|(?:([^\\\\])\\\\n)","$1\n");
277
        System.out.println("#"+s1+"#");
278
        String s2 = s1.replaceAll("([^\\\\])\\\\r","$1{r}");
279
        System.out.println("#"+s2+"#");
280
        String s3 = StringEscapeUtils.unescapeCsv(s0);
281
        System.out.println("#"+s3+"#");
282
    }
283
    
284
    
285
    public static File getIndexFile(File data_file) {
286
        if (data_file == null){
287
            return null;
288
        }
289
        File index_file = new File(FilenameUtils.removeExtension(data_file.getAbsolutePath()) + ".idx");
290
        return index_file;
291
    }
292

    
293
}