7
7
using System . Text . RegularExpressions ;
8
8
using System . Threading ;
9
9
using System . Threading . Tasks ;
10
+ using MiniExcelLibs . Exceptions ;
10
11
11
12
namespace MiniExcelLibs . Csv
12
13
{
13
14
internal class CsvReader : IExcelReader
14
15
{
15
16
private Stream _stream ;
16
17
private CsvConfiguration _config ;
18
+
17
19
public CsvReader ( Stream stream , IConfiguration configuration )
18
20
{
19
- this . _stream = stream ;
20
- this . _config = configuration == null ? CsvConfiguration . DefaultConfiguration : ( CsvConfiguration ) configuration ;
21
+ _stream = stream ;
22
+ _config = configuration == null ? CsvConfiguration . DefaultConfiguration : ( CsvConfiguration ) configuration ;
21
23
}
22
24
public IEnumerable < IDictionary < string , object > > Query ( bool useHeaderRow , string sheetName , string startCell )
23
25
{
24
26
if ( startCell != "A1" )
25
- throw new NotImplementedException ( "CSV not Implement startCell" ) ;
27
+ throw new NotImplementedException ( "CSV does not implement parameter startCell" ) ;
28
+
26
29
if ( _stream . CanSeek )
27
30
_stream . Position = 0 ;
31
+
28
32
var reader = _config . StreamReaderFunc ( _stream ) ;
33
+ var firstRow = true ;
34
+ var headRows = new Dictionary < int , string > ( ) ;
35
+
36
+ string row ;
37
+ for ( var rowIndex = 1 ; ( row = reader . ReadLine ( ) ) != null ; rowIndex ++ )
29
38
{
30
- string [ ] read ;
31
- var firstRow = true ;
32
- Dictionary < int , string > headRows = new Dictionary < int , string > ( ) ;
33
- string row ;
34
- for ( var rowIndex = 1 ; ( row = reader . ReadLine ( ) ) != null ; rowIndex ++ )
39
+ string finalRow = row ;
40
+ if ( _config . ReadLineBreaksWithinQuotes )
35
41
{
36
-
37
- string finalRow = row ;
38
- if ( _config . ReadLineBreaksWithinQuotes )
42
+ while ( finalRow . Count ( c => c == '"' ) % 2 != 0 )
39
43
{
40
- while ( finalRow . Count ( c => c == '"' ) % 2 != 0 )
44
+ var nextPart = reader . ReadLine ( ) ;
45
+ if ( nextPart == null )
41
46
{
42
- var nextPart = reader . ReadLine ( ) ;
43
- if ( nextPart == null )
44
- {
45
- break ;
46
- }
47
- finalRow = string . Concat ( finalRow , _config . NewLine , nextPart ) ;
47
+ break ;
48
48
}
49
+ finalRow = string . Concat ( finalRow , _config . NewLine , nextPart ) ;
49
50
}
50
- read = Split ( finalRow ) ;
51
+ }
52
+ var read = Split ( finalRow ) ;
51
53
52
- // invalid row check
53
- if ( read . Length < headRows . Count )
54
- {
55
- var colIndex = read . Length ;
56
- var headers = headRows . ToDictionary ( x => x . Value , x => x . Key ) ;
57
- var rowValues = read . Select ( ( x , i ) => new { Key = headRows [ i ] , Value = x } ) . ToDictionary ( x => x . Key , x => ( object ) x . Value ) ;
58
- throw new Exceptions . ExcelColumnNotFoundException ( null ,
59
- headRows [ colIndex ] , null , rowIndex , headers , rowValues , $ "Csv read error, Column: { colIndex } not found in Row: { rowIndex } ") ;
60
- }
54
+ // invalid row check
55
+ if ( read . Length < headRows . Count )
56
+ {
57
+ var colIndex = read . Length ;
58
+ var headers = headRows . ToDictionary ( x => x . Value , x => x . Key ) ;
59
+ var rowValues = read
60
+ . Select ( ( x , i ) => new KeyValuePair < string , object > ( headRows [ i ] , x ) )
61
+ . ToDictionary ( x => x . Key , x => x . Value ) ;
62
+
63
+ throw new ExcelColumnNotFoundException ( columnIndex : null , headRows [ colIndex ] , null , rowIndex , headers , rowValues , $ "Csv read error: Column { colIndex } not found in Row { rowIndex } ") ;
64
+ }
61
65
62
- //header
63
- if ( useHeaderRow )
66
+ //header
67
+ if ( useHeaderRow )
68
+ {
69
+ if ( firstRow )
64
70
{
65
- if ( firstRow )
66
- {
67
- firstRow = false ;
68
- for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
69
- headRows . Add ( i , read [ i ] ) ;
70
- continue ;
71
- }
72
-
73
- var cell = CustomPropertyHelper . GetEmptyExpandoObject ( headRows ) ;
71
+ firstRow = false ;
74
72
for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
75
- cell [ headRows [ i ] ] = read [ i ] ;
76
-
77
- yield return cell ;
73
+ headRows . Add ( i , read [ i ] ) ;
78
74
continue ;
79
75
}
80
76
77
+ var headCell = CustomPropertyHelper . GetEmptyExpandoObject ( headRows ) ;
78
+ for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
79
+ headCell [ headRows [ i ] ] = read [ i ] ;
81
80
82
- //body
83
- {
84
- // record first row as reference
85
- if ( firstRow )
86
- {
87
- firstRow = false ;
88
- for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
89
- headRows . Add ( i , $ "c{ i + 1 } ") ;
90
- }
81
+ yield return headCell ;
82
+ continue ;
83
+ }
91
84
92
- var cell = CustomPropertyHelper . GetEmptyExpandoObject ( read . Length - 1 , 0 ) ;
93
- if ( _config . ReadEmptyStringAsNull )
94
- {
95
- for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
96
- cell [ ColumnHelper . GetAlphabetColumnName ( i ) ] = read [ i ] ? . Length == 0 ? null : read [ i ] ;
97
- }
98
- else
99
- {
100
- for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
101
- cell [ ColumnHelper . GetAlphabetColumnName ( i ) ] = read [ i ] ;
102
- }
85
+ //body
86
+ if ( firstRow ) // record first row as reference
87
+ {
88
+ firstRow = false ;
89
+ for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
90
+ headRows . Add ( i , $ "c{ i + 1 } ") ;
91
+ }
103
92
104
- yield return cell ;
105
- }
93
+ var cell = CustomPropertyHelper . GetEmptyExpandoObject ( read . Length - 1 , 0 ) ;
94
+ if ( _config . ReadEmptyStringAsNull )
95
+ {
96
+ for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
97
+ cell [ ColumnHelper . GetAlphabetColumnName ( i ) ] = read [ i ] ? . Length == 0 ? null : read [ i ] ;
106
98
}
99
+ else
100
+ {
101
+ for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
102
+ cell [ ColumnHelper . GetAlphabetColumnName ( i ) ] = read [ i ] ;
103
+ }
104
+
105
+ yield return cell ;
107
106
}
108
107
}
109
108
public IEnumerable < T > Query < T > ( string sheetName , string startCell , bool hasHeader ) where T : class , new ( )
110
109
{
111
- return ExcelOpenXmlSheetReader . QueryImpl < T > ( Query ( false , sheetName , startCell ) , startCell , hasHeader , _config ) ;
110
+ var dynamicRecords = Query ( false , sheetName , startCell ) ;
111
+ return ExcelOpenXmlSheetReader . QueryImpl < T > ( dynamicRecords , startCell , hasHeader , _config ) ;
112
112
}
113
113
114
114
private string [ ] Split ( string row )
@@ -119,9 +119,10 @@ private string[] Split(string row)
119
119
}
120
120
else
121
121
{
122
- return Regex . Split ( row , $ "[\t { _config . Seperator } ](?=(?:[^\" ]|\" [^\" ]*\" )*$)")
123
- . Select ( s => Regex . Replace ( s . Replace ( "\" \" " , "\" " ) , "^\" |\" $" , "" ) ) . ToArray ( ) ;
124
122
//this code from S.O : https://stackoverflow.com/a/11365961/9131476
123
+ return Regex . Split ( row , $ "[\t { _config . Seperator } ](?=(?:[^\" ]|\" [^\" ]*\" )*$)")
124
+ . Select ( s => Regex . Replace ( s . Replace ( "\" \" " , "\" " ) , "^\" |\" $" , "" ) )
125
+ . ToArray ( ) ;
125
126
}
126
127
}
127
128
@@ -143,56 +144,55 @@ public void Dispose()
143
144
public IEnumerable < IDictionary < string , object > > QueryRange ( bool useHeaderRow , string sheetName , string startCell , string endCell )
144
145
{
145
146
if ( startCell != "A1" )
146
- throw new NotImplementedException ( "CSV not Implement startCell" ) ;
147
+ throw new NotImplementedException ( "CSV does not implement parameter startCell" ) ;
148
+
147
149
if ( _stream . CanSeek )
148
150
_stream . Position = 0 ;
151
+
149
152
var reader = _config . StreamReaderFunc ( _stream ) ;
153
+
154
+ string row ;
155
+ var firstRow = true ;
156
+ var headRows = new Dictionary < int , string > ( ) ;
157
+
158
+ while ( ( row = reader . ReadLine ( ) ) != null )
150
159
{
151
- var row = string . Empty ;
152
- string [ ] read ;
153
- var firstRow = true ;
154
- Dictionary < int , string > headRows = new Dictionary < int , string > ( ) ;
155
- while ( ( row = reader . ReadLine ( ) ) != null )
156
- {
157
- read = Split ( row ) ;
160
+ var read = Split ( row ) ;
158
161
159
- //header
160
- if ( useHeaderRow )
162
+ //header
163
+ if ( useHeaderRow )
164
+ {
165
+ if ( firstRow )
161
166
{
162
- if ( firstRow )
163
- {
164
- firstRow = false ;
165
- for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
166
- headRows . Add ( i , read [ i ] ) ;
167
- continue ;
168
- }
169
-
170
- var cell = CustomPropertyHelper . GetEmptyExpandoObject ( headRows ) ;
167
+ firstRow = false ;
171
168
for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
172
- cell [ headRows [ i ] ] = read [ i ] ;
173
-
174
- yield return cell ;
169
+ headRows . Add ( i , read [ i ] ) ;
175
170
continue ;
176
171
}
177
172
173
+ var headCell = CustomPropertyHelper . GetEmptyExpandoObject ( headRows ) ;
174
+ for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
175
+ headCell [ headRows [ i ] ] = read [ i ] ;
178
176
179
- //body
180
- {
181
- var cell = CustomPropertyHelper . GetEmptyExpandoObject ( read . Length - 1 , 0 ) ;
182
- for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
183
- cell [ ColumnHelper . GetAlphabetColumnName ( i ) ] = read [ i ] ;
184
- yield return cell ;
185
- }
177
+ yield return headCell ;
178
+ continue ;
186
179
}
180
+
181
+ //body
182
+ var cell = CustomPropertyHelper . GetEmptyExpandoObject ( read . Length - 1 , 0 ) ;
183
+ for ( int i = 0 ; i <= read . Length - 1 ; i ++ )
184
+ cell [ ColumnHelper . GetAlphabetColumnName ( i ) ] = read [ i ] ;
185
+
186
+ yield return cell ;
187
187
}
188
188
}
189
189
public IEnumerable < T > QueryRange < T > ( string sheetName , string startCell , string endCel ) where T : class , new ( )
190
190
{
191
191
return ExcelOpenXmlSheetReader . QueryImplRange < T > ( QueryRange ( false , sheetName , startCell , endCel ) , startCell , endCel , this . _config ) ;
192
192
}
193
- public Task < IEnumerable < IDictionary < string , object > > > QueryAsyncRange ( bool UseHeaderRow , string sheetName , string startCell , string endCel , CancellationToken cancellationToken = default )
193
+ public Task < IEnumerable < IDictionary < string , object > > > QueryAsyncRange ( bool useHeaderRow , string sheetName , string startCell , string endCel , CancellationToken cancellationToken = default )
194
194
{
195
- return Task . Run ( ( ) => QueryRange ( UseHeaderRow , sheetName , startCell , endCel ) , cancellationToken ) ;
195
+ return Task . Run ( ( ) => QueryRange ( useHeaderRow , sheetName , startCell , endCel ) , cancellationToken ) ;
196
196
}
197
197
198
198
public Task < IEnumerable < T > > QueryAsyncRange < T > ( string sheetName , string startCell , string endCel , bool hasHeader , CancellationToken cancellationToken = default ) where T : class , new ( )
0 commit comments