If I have a script like this
import 'package:path/path.dart' as p;
import 'dart:io';
import 'dart:async';
void main() async {
final inDir = p.join(Directory.current.path, 'tmp', 'in'); // should we rename this
var dir = Directory(inDir);
final List<FileSystemEntity> fileList = await dir.list().toList();
for (var file in fileList.where((entity) => entity is File) ) {
print ("Processing ${(file as File).toString()}");
final contents = (file as File).readAsStringSync();
print (contents);
}
}
it works fine.
Processing File: 'C:\FlutterProjects\project\tmp\a.txt'
some text
However if I want to get the file path to pass to another function as a string
import 'package:path/path.dart' as p;
import 'dart:io';
import 'dart:async';
void main() async {
final inDir = p.join(Directory.current.path, 'tmp'); // should we rename this
var dir = Directory(inDir);
final List<FileSystemEntity> fileList = await dir.list().toList();
for (var file in fileList.where((entity) => entity is File) ) {
print ("Processing ${(file as File).toString()}");
readFile ((file as File).toString());
}
}
void readFile (String filePath) {
final file = File(filePath);
final contents = file.readAsStringSync();
print (contents);
}
... then it doesn't work...
Processing File: 'C:\FlutterProjects\project\tmp\a.txt'
Unhandled exception:
FileSystemException: Cannot open file, path = 'File: 'C:\FlutterProjects\project\tmp\a.txt'' (OS Error: The filename, directory name, or volume label syntax is incorrect.
, errno = 123)
#0 _File.throwIfError (dart:io/file_impl.dart:675:7)
#1 _File.openSync (dart:io/file_impl.dart:490:5)
#2 _File.readAsBytesSync (dart:io/file_impl.dart:574:18)
#3 _File.readAsStringSync (dart:io/file_impl.dart:624:18)
#4 readFile (file:///C:/FlutterProjects/project/bin/parse-files.dart:18:27)
#5 main (file:///C:/FlutterProjects/project/bin/parse-files.dart:11:5)
<asynchronous suspension>
I am guessing because it still has File: at the beginning. So I could treat that as an entity in the function itself or I transform the string to not have File: a the beginning but I don't understand why it is not sending the string of the file as a file (which is what I would like to do keep the function more reusable).
TL;DR why doesn't ((file as File).toString());
do what I expect when file is a FileEntity.
The output of calling toString()
on a File object are not a path you can use for something. If you see your code, the result of calling toString()
on your File
are actually the String:
File: 'C:\FlutterProjects\project\tmp\a.txt'
So what you are actually ended up doing, are calling:
File("File: 'C:\FlutterProjects\project\tmp\a.txt'");
Which fails since that is not a valid path and not something you can read from.
Instead of calling toString()
, you should use the .path
property on the File
object. Or just send the File
as argument to your method:
import 'package:path/path.dart' as p;
import 'dart:io';
void main() async {
final inDir = p.join(Directory.current.path, 'tmp'); // should we rename this
var dir = Directory(inDir);
final List<FileSystemEntity> fileList = await dir.list().toList();
for (var file in fileList.whereType<File>()) {
print("Processing ${file.path}");
readFile(file);
}
}
void readFile(File file) {
final contents = file.readAsStringSync();
print(contents);
}
Also, I have fixed your unneeded casting of file types in this code. If you use whereType
, it actually filter based on type checking and returns the right type of objects.