@@ -25,6 +25,7 @@ import fs from 'fs'
25
25
* hence all PapaParse options are supported.
26
26
* @param options Configuration object. Supports all Papaparse parse config options.
27
27
* @returns DataFrame containing the parsed CSV file.
28
+ * @throws {Error } If file cannot be read or parsed
28
29
* @example
29
30
* ```
30
31
* import { readCSV } from "danfojs-node"
@@ -52,6 +53,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
52
53
53
54
if ( filePath . startsWith ( "http" ) || filePath . startsWith ( "https" ) ) {
54
55
return new Promise ( ( resolve , reject ) => {
56
+ let hasError = false ;
55
57
const optionsWithDefaults = {
56
58
header : true ,
57
59
dynamicTyping : true ,
@@ -63,6 +65,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
63
65
// reject any non-2xx status codes
64
66
dataStream . on ( 'response' , ( response : any ) => {
65
67
if ( response . statusCode < 200 || response . statusCode >= 300 ) {
68
+ hasError = true ;
66
69
reject ( new Error ( `HTTP ${ response . statusCode } : ${ response . statusMessage } ` ) ) ;
67
70
}
68
71
} ) ;
@@ -72,30 +75,73 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
72
75
73
76
const data : any = [ ] ;
74
77
parseStream . on ( "data" , ( chunk : any ) => {
75
- data . push ( chunk ) ;
78
+ if ( ! hasError ) {
79
+ data . push ( chunk ) ;
80
+ }
81
+ } ) ;
82
+
83
+ parseStream . on ( "error" , ( error : any ) => {
84
+ hasError = true ;
85
+ reject ( new Error ( `Failed to parse CSV: ${ error . message } ` ) ) ;
76
86
} ) ;
77
87
78
88
parseStream . on ( "finish" , ( ) => {
79
- resolve ( new DataFrame ( data , frameConfig ) ) ;
89
+ if ( hasError ) return ;
90
+
91
+ if ( ! data || data . length === 0 ) {
92
+ reject ( new Error ( 'No data found in CSV file' ) ) ;
93
+ return ;
94
+ }
95
+
96
+ try {
97
+ const df = new DataFrame ( data , frameConfig ) ;
98
+ resolve ( df ) ;
99
+ } catch ( error ) {
100
+ const errorMessage = error instanceof Error ? error . message : 'Unknown error occurred' ;
101
+ reject ( new Error ( `Failed to create DataFrame: ${ errorMessage } ` ) ) ;
102
+ }
80
103
} ) ;
81
104
} ) ;
82
105
83
106
} else {
84
107
return new Promise ( ( resolve , reject ) => {
85
108
fs . access ( filePath , fs . constants . F_OK , ( err ) => {
86
109
if ( err ) {
87
- reject ( "ENOENT: no such file or directory" ) ;
110
+ reject ( new Error ( "ENOENT: no such file or directory" ) ) ;
111
+ return ;
88
112
}
89
113
90
114
const fileStream = fs . createReadStream ( filePath )
115
+ let hasError = false ;
91
116
92
117
Papa . parse ( fileStream , {
93
118
header : true ,
94
119
dynamicTyping : true ,
95
120
...options ,
121
+ error : ( error ) => {
122
+ hasError = true ;
123
+ reject ( new Error ( `Failed to parse CSV: ${ error . message } ` ) ) ;
124
+ } ,
96
125
complete : results => {
97
- const df = new DataFrame ( results . data , frameConfig ) ;
98
- resolve ( df ) ;
126
+ if ( hasError ) return ;
127
+
128
+ if ( ! results . data || results . data . length === 0 ) {
129
+ reject ( new Error ( 'No data found in CSV file' ) ) ;
130
+ return ;
131
+ }
132
+
133
+ if ( results . errors && results . errors . length > 0 ) {
134
+ reject ( new Error ( `CSV parsing errors: ${ results . errors . map ( e => e . message ) . join ( ', ' ) } ` ) ) ;
135
+ return ;
136
+ }
137
+
138
+ try {
139
+ const df = new DataFrame ( results . data , frameConfig ) ;
140
+ resolve ( df ) ;
141
+ } catch ( error ) {
142
+ const errorMessage = error instanceof Error ? error . message : 'Unknown error occurred' ;
143
+ reject ( new Error ( `Failed to create DataFrame: ${ errorMessage } ` ) ) ;
144
+ }
99
145
}
100
146
} ) ;
101
147
} )
@@ -109,6 +155,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
109
155
* hence all PapaParse options are supported.
110
156
* @param callback Callback function to be called once the specifed rows are parsed into DataFrame.
111
157
* @param options Configuration object. Supports all Papaparse parse config options.
158
+ * @throws {Error } If file cannot be read or parsed
112
159
* @example
113
160
* ```
114
161
* import { streamCSV } from "danfojs-node"
@@ -128,12 +175,14 @@ const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, o
128
175
...options ,
129
176
}
130
177
return new Promise ( ( resolve , reject ) => {
131
- let count = 0
178
+ let count = 0 ;
179
+ let hasError = false ;
132
180
const dataStream = request . get ( filePath ) ;
133
181
134
182
// reject any non-2xx status codes
135
183
dataStream . on ( 'response' , ( response : any ) => {
136
184
if ( response . statusCode < 200 || response . statusCode >= 300 ) {
185
+ hasError = true ;
137
186
reject ( new Error ( `HTTP ${ response . statusCode } : ${ response . statusMessage } ` ) ) ;
138
187
}
139
188
} ) ;
@@ -142,35 +191,71 @@ const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, o
142
191
dataStream . pipe ( parseStream ) ;
143
192
144
193
parseStream . on ( "data" , ( chunk : any ) => {
145
- const df = new DataFrame ( [ chunk ] , { ...frameConfig , index : [ count ++ ] , } ) ;
146
- callback ( df ) ;
194
+ if ( hasError ) return ;
195
+ try {
196
+ const df = new DataFrame ( [ chunk ] , { ...frameConfig , index : [ count ++ ] } ) ;
197
+ callback ( df ) ;
198
+ } catch ( error ) {
199
+ hasError = true ;
200
+ const errorMessage = error instanceof Error ? error . message : 'Unknown error occurred' ;
201
+ reject ( new Error ( `Failed to process CSV chunk: ${ errorMessage } ` ) ) ;
202
+ }
147
203
} ) ;
148
204
149
- parseStream . on ( "finish" , ( ) => {
150
- resolve ( null ) ;
205
+ parseStream . on ( "error" , ( error : any ) => {
206
+ hasError = true ;
207
+ reject ( new Error ( `Failed to parse CSV: ${ error . message } ` ) ) ;
151
208
} ) ;
152
209
210
+ parseStream . on ( "finish" , ( ) => {
211
+ if ( ! hasError ) {
212
+ resolve ( null ) ;
213
+ }
214
+ } ) ;
153
215
} ) ;
154
216
} else {
155
-
156
217
return new Promise ( ( resolve , reject ) => {
157
218
fs . access ( filePath , fs . constants . F_OK , ( err ) => {
158
219
if ( err ) {
159
- reject ( "ENOENT: no such file or directory" ) ;
220
+ reject ( new Error ( "ENOENT: no such file or directory" ) ) ;
221
+ return ;
160
222
}
161
223
162
224
const fileStream = fs . createReadStream ( filePath )
225
+ let hasError = false ;
226
+ let count = 0 ;
163
227
164
- let count = 0
165
228
Papa . parse ( fileStream , {
166
229
header : true ,
167
230
dynamicTyping : true ,
168
231
...options ,
232
+ error : ( error ) => {
233
+ hasError = true ;
234
+ reject ( new Error ( `Failed to parse CSV: ${ error . message } ` ) ) ;
235
+ } ,
169
236
step : results => {
170
- const df = new DataFrame ( [ results . data ] , { ...frameConfig , index : [ count ++ ] } ) ;
171
- callback ( df ) ;
237
+ if ( hasError ) return ;
238
+
239
+ if ( results . errors && results . errors . length > 0 ) {
240
+ hasError = true ;
241
+ reject ( new Error ( `CSV parsing errors: ${ results . errors . map ( e => e . message ) . join ( ', ' ) } ` ) ) ;
242
+ return ;
243
+ }
244
+
245
+ try {
246
+ const df = new DataFrame ( [ results . data ] , { ...frameConfig , index : [ count ++ ] } ) ;
247
+ callback ( df ) ;
248
+ } catch ( error ) {
249
+ hasError = true ;
250
+ const errorMessage = error instanceof Error ? error . message : 'Unknown error occurred' ;
251
+ reject ( new Error ( `Failed to process CSV chunk: ${ errorMessage } ` ) ) ;
252
+ }
172
253
} ,
173
- complete : ( ) => resolve ( null )
254
+ complete : ( ) => {
255
+ if ( ! hasError ) {
256
+ resolve ( null ) ;
257
+ }
258
+ }
174
259
} ) ;
175
260
} ) ;
176
261
} ) ;
0 commit comments