Skip to content

Commit 3d7808e

Browse files
LiviaMedeirostargos
authored andcommitted
fs: add read(buffer[, options]) versions
This adds the following: - `fs.read(fd, buffer[, options], callback)`. - `filehandle.read(buffer[, options])`. PR-URL: #42768 Refs: #42601 Reviewed-By: Antoine du Hamel <[email protected]>
1 parent cc398a8 commit 3d7808e

File tree

6 files changed

+151
-54
lines changed

6 files changed

+151
-54
lines changed

‎doc/api/fs.md‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,33 @@ Reads data from the file and stores that in the given buffer.
417417
If the file is not modified concurrently, the end-of-file is reached when the
418418
number of bytes read is zero.
419419
420+
#### `filehandle.read(buffer[, options])`
421+
422+
<!-- YAML
423+
added: REPLACEME
424+
-->
425+
426+
* `buffer`{Buffer|TypedArray|DataView} A buffer that will be filled with the
427+
file data read.
428+
* `options`{Object}
429+
* `offset`{integer} The location in the buffer at which to start filling.
430+
**Default:** `0`
431+
* `length`{integer} The number of bytes to read. **Default:**
432+
`buffer.byteLength- offset`
433+
* `position`{integer} The location where to begin reading data from the
434+
file. If `null`, data will be read from the current file position, and
435+
the position will be updated. If `position` is an integer, the current
436+
file position will remain unchanged. **Default:**: `null`
437+
* Returns:{Promise} Fulfills upon success with an object with two properties:
438+
* `bytesRead`{integer} The number of bytes read
439+
* `buffer`{Buffer|TypedArray|DataView} A reference to the passed in `buffer`
440+
argument.
441+
442+
Reads data from the file and stores that in the given buffer.
443+
444+
If the file is not modified concurrently, the end-of-file is reached when the
445+
number of bytes read is zero.
446+
420447
#### `filehandle.readFile(options)`
421448
422449
<!-- YAML
@@ -3088,6 +3115,28 @@ Similar to the [`fs.read()`][] function, this version takes an optional
30883115
`options` object. If no `options` object is specified, it will default with the
30893116
above values.
30903117
3118+
### `fs.read(fd, buffer[, options], callback)`
3119+
3120+
<!-- YAML
3121+
added: REPLACEME
3122+
-->
3123+
3124+
* `fd`{integer}
3125+
* `buffer`{Buffer|TypedArray|DataView} The buffer that the data will be
3126+
written to.
3127+
* `options`{Object}
3128+
* `offset`{integer} **Default:** `0`
3129+
* `length`{integer} **Default:** `buffer.byteLength- offset`
3130+
* `position`{integer|bigint} **Default:** `null`
3131+
* `callback`{Function}
3132+
* `err`{Error}
3133+
* `bytesRead`{integer}
3134+
* `buffer`{Buffer}
3135+
3136+
Similar to the [`fs.read()`][] function, this version takes an optional
3137+
`options` object. If no `options` object is specified, it will default with the
3138+
above values.
3139+
30913140
### `fs.readdir(path[, options], callback)`
30923141
30933142
<!-- YAML

‎lib/fs.js‎

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ const{
137137
validateEncoding,
138138
validateFunction,
139139
validateInteger,
140+
validateObject,
140141
validateString,
141142
}=require('internal/validators');
142143

@@ -591,7 +592,7 @@ function openSync(path, flags, mode){
591592
* Reads file from the specified `fd` (file descriptor).
592593
* @param{number} fd
593594
* @param{Buffer | TypedArray | DataView} buffer
594-
* @param{number} offset
595+
* @param{number} offsetOrOptions
595596
* @param{number} length
596597
* @param{number | bigint | null} position
597598
* @param{(
@@ -601,30 +602,36 @@ function openSync(path, flags, mode){
601602
* ) => any} callback
602603
* @returns{void}
603604
*/
604-
functionread(fd,buffer,offset,length,position,callback){
605+
functionread(fd,buffer,offsetOrOptions,length,position,callback){
605606
fd=getValidatedFd(fd);
606607

607-
if(arguments.length<=3){
608-
// Assume fs.read(fd, options, callback)
609-
letoptions=ObjectCreate(null);
610-
if(arguments.length<3){
608+
letoffset=offsetOrOptions;
609+
letparams=null;
610+
if(arguments.length<=4){
611+
if(arguments.length===4){
612+
// This is fs.read(fd, buffer, options, callback)
613+
validateObject(offsetOrOptions,'options',{nullable: true});
614+
callback=length;
615+
params=offsetOrOptions;
616+
}elseif(arguments.length===3){
617+
// This is fs.read(fd, bufferOrParams, callback)
618+
if(!isArrayBufferView(buffer)){
619+
// This is fs.read(fd, params, callback)
620+
params=buffer;
621+
({ buffer =Buffer.alloc(16384)}=params??ObjectCreate(null));
622+
}
623+
callback=offsetOrOptions;
624+
}else{
611625
// This is fs.read(fd, callback)
612-
// buffer will be the callback
613626
callback=buffer;
614-
}else{
615-
// This is fs.read(fd,{}, callback)
616-
// buffer will be the options object
617-
// offset is the callback
618-
options=buffer;
619-
callback=offset;
627+
buffer=Buffer.alloc(16384);
620628
}
621629

622630
({
623-
buffer =Buffer.alloc(16384),
624631
offset =0,
625632
length =buffer.byteLength-offset,
626633
position =null
627-
}=options);
634+
}=params??ObjectCreate(null));
628635
}
629636

630637
validateBuffer(buffer);

‎lib/internal/fs/promises.js‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,20 +456,29 @@ async function open(path, flags, mode){
456456
flagsNumber,mode,kUsePromises));
457457
}
458458

459-
asyncfunctionread(handle,bufferOrOptions,offset,length,position){
460-
letbuffer=bufferOrOptions;
459+
asyncfunctionread(handle,bufferOrParams,offset,length,position){
460+
letbuffer=bufferOrParams;
461461
if(!isArrayBufferView(buffer)){
462-
bufferOrOptions??=ObjectCreate(null);
462+
// This is fh.read(params)
463463
({
464464
buffer =Buffer.alloc(16384),
465465
offset =0,
466466
length =buffer.byteLength-offset,
467467
position =null
468-
}=bufferOrOptions);
468+
}=bufferOrParams??ObjectCreate(null));
469469

470470
validateBuffer(buffer);
471471
}
472472

473+
if(offset!==null&&typeofoffset==='object'){
474+
// This is fh.read(buffer, options)
475+
({
476+
offset =0,
477+
length =buffer.byteLength-offset,
478+
position =null
479+
}=offset??ObjectCreate(null));
480+
}
481+
473482
if(offset==null){
474483
offset=0;
475484
}else{

‎test/parallel/test-fs-read-offset-null.js‎

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,51 @@ const filepath = fixtures.path('x.txt');
1414
constbuf=Buffer.alloc(1);
1515
// Reading only one character, hence buffer of one byte is enough.
1616

17-
// Test for callback API.
17+
// Tests are done by making sure the first letter in buffer is
18+
// same as first letter in file.
19+
// 120 is the ascii code of letter x.
20+
21+
// Tests for callback API.
1822
fs.open(filepath,'r',common.mustSucceed((fd)=>{
1923
fs.read(fd,{offset: null,buffer: buf},
2024
common.mustSucceed((bytesRead,buffer)=>{
21-
// Test is done by making sure the first letter in buffer is
22-
// same as first letter in file.
23-
// 120 is the hex for ascii code of letter x.
25+
assert.strictEqual(buffer[0],120);
26+
fs.close(fd,common.mustSucceed(()=>{}));
27+
}));
28+
}));
29+
30+
fs.open(filepath,'r',common.mustSucceed((fd)=>{
31+
fs.read(fd,buf,{offset: null},
32+
common.mustSucceed((bytesRead,buffer)=>{
2433
assert.strictEqual(buffer[0],120);
2534
fs.close(fd,common.mustSucceed(()=>{}));
2635
}));
2736
}));
2837

2938
letfilehandle=null;
3039

31-
// Test for promise api
40+
// Tests for promises api
41+
(async()=>{
42+
filehandle=awaitfsPromises.open(filepath,'r');
43+
constreadObject=awaitfilehandle.read(buf,{offset: null});
44+
assert.strictEqual(readObject.buffer[0],120);
45+
})()
46+
.finally(()=>filehandle?.close())
47+
.then(common.mustCall());
48+
49+
// Undocumented: omitted position works the same as position === null
3250
(async()=>{
3351
filehandle=awaitfsPromises.open(filepath,'r');
3452
constreadObject=awaitfilehandle.read(buf,null,buf.length);
3553
assert.strictEqual(readObject.buffer[0],120);
3654
})()
37-
.then(common.mustCall())
38-
.finally(async()=>{
39-
// Close the file handle if it is opened
40-
if(filehandle)
41-
awaitfilehandle.close();
42-
});
55+
.finally(()=>filehandle?.close())
56+
.then(common.mustCall());
57+
58+
(async()=>{
59+
filehandle=awaitfsPromises.open(filepath,'r');
60+
constreadObject=awaitfilehandle.read(buf,null,buf.length,0);
61+
assert.strictEqual(readObject.buffer[0],120);
62+
})()
63+
.finally(()=>filehandle?.close())
64+
.then(common.mustCall());

‎test/parallel/test-fs-read-optional-params.js‎

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,34 @@ const fixtures = require('../common/fixtures');
55
constfs=require('fs');
66
constassert=require('assert');
77
constfilepath=fixtures.path('x.txt');
8-
constfd=fs.openSync(filepath,'r');
98

109
constexpected=Buffer.from('xyz\n');
1110
constdefaultBufferAsync=Buffer.alloc(16384);
12-
constbufferAsOption=Buffer.allocUnsafe(expected.length);
11+
constbufferAsOption=Buffer.allocUnsafe(expected.byteLength);
1312

14-
// Test not passing in any options object
15-
fs.read(fd,common.mustCall((err,bytesRead,buffer)=>{
16-
assert.strictEqual(bytesRead,expected.length);
17-
assert.deepStrictEqual(defaultBufferAsync.length,buffer.length);
18-
}));
13+
functiontestValid(message, ...options){
14+
constparamsMsg=`${message} (as params)`;
15+
constparamsFilehandle=fs.openSync(filepath,'r');
16+
fs.read(paramsFilehandle, ...options,common.mustSucceed((bytesRead,buffer)=>{
17+
assert.strictEqual(bytesRead,expected.byteLength,paramsMsg);
18+
assert.deepStrictEqual(defaultBufferAsync.byteLength,buffer.byteLength,paramsMsg);
19+
fs.closeSync(paramsFilehandle);
20+
}));
1921

20-
// Test passing in an empty options object
21-
fs.read(fd,{position: 0},common.mustCall((err,bytesRead,buffer)=>{
22-
assert.strictEqual(bytesRead,expected.length);
23-
assert.deepStrictEqual(defaultBufferAsync.length,buffer.length);
24-
}));
22+
constoptionsMsg=`${message} (as options)`;
23+
constoptionsFilehandle=fs.openSync(filepath,'r');
24+
fs.read(optionsFilehandle,bufferAsOption, ...options,common.mustSucceed((bytesRead,buffer)=>{
25+
assert.strictEqual(bytesRead,expected.byteLength,optionsMsg);
26+
assert.deepStrictEqual(bufferAsOption.byteLength,buffer.byteLength,optionsMsg);
27+
fs.closeSync(optionsFilehandle);
28+
}));
29+
}
2530

26-
// Test passing in options
27-
fs.read(fd,{
28-
buffer: bufferAsOption,
31+
testValid('Not passing in any object');
32+
testValid('Passing in a null',null);
33+
testValid('Passing in an empty object',{});
34+
testValid('Passing in an object',{
2935
offset: 0,
30-
length: bufferAsOption.length,
31-
position: 0
32-
},
33-
common.mustCall((err,bytesRead,buffer)=>{
34-
assert.strictEqual(bytesRead,expected.length);
35-
assert.deepStrictEqual(bufferAsOption.length,buffer.length);
36-
}));
36+
length: bufferAsOption.byteLength,
37+
position: 0,
38+
});

‎test/parallel/test-fs-read-promises-optional-params.js‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@ const fd = fs.openSync(filepath, 'r');
1010

1111
constexpected=Buffer.from('xyz\n');
1212
constdefaultBufferAsync=Buffer.alloc(16384);
13+
constbufferAsOption=Buffer.allocUnsafe(expected.byteLength);
1314

1415
read(fd,{})
1516
.then(function({ bytesRead, buffer }){
16-
assert.strictEqual(bytesRead,expected.length);
17-
assert.deepStrictEqual(defaultBufferAsync.length,buffer.length);
17+
assert.strictEqual(bytesRead,expected.byteLength);
18+
assert.deepStrictEqual(defaultBufferAsync.byteLength,buffer.byteLength);
19+
})
20+
.then(common.mustCall());
21+
22+
read(fd,bufferAsOption,{position: 0})
23+
.then(function({ bytesRead, buffer }){
24+
assert.strictEqual(bytesRead,expected.byteLength);
25+
assert.deepStrictEqual(bufferAsOption.byteLength,buffer.byteLength);
1826
})
1927
.then(common.mustCall());

0 commit comments

Comments
(0)