Make MemoryFile.openRead and _ChrootFile.openRead return Stream<List<int>> again (#217)

* Make MemoryFile.openRead and _ChrootFile.openRead return Stream<List<int>> again

This is equivalent to https://github.com/google/file.dart/pull/168,
but I foolishly neglected to make corresponding changes for all
file system types.

Fixes https://github.com/google/file.dart/issues/193.

* Apply suggestions from natebosch

Co-authored-by: Nate Bosch <nbosch1@gmail.com>

---------

Co-authored-by: Nate Bosch <nbosch1@gmail.com>
diff --git a/packages/file/CHANGELOG.md b/packages/file/CHANGELOG.md
index 6e46da0..f7eb965 100644
--- a/packages/file/CHANGELOG.md
+++ b/packages/file/CHANGELOG.md
@@ -3,6 +3,8 @@
 * Dart 3 fixes for class modifiers.
 * `MemoryFileSystem` now treats empty paths as non-existent.
 * Fix `FileSystem.isLink`/`FileSystem.isLinkSync` to not follow symbolic links.
+* Make the return type of `MemoryFile.openRead` and `_ChrootFile.openRead` again
+  match the return type from `dart:io`.
 
 #### 6.1.4
 
diff --git a/packages/file/lib/src/backends/chroot/chroot_file.dart b/packages/file/lib/src/backends/chroot/chroot_file.dart
index ed340d6..4b67bc1 100644
--- a/packages/file/lib/src/backends/chroot/chroot_file.dart
+++ b/packages/file/lib/src/backends/chroot/chroot_file.dart
@@ -251,8 +251,8 @@
           path, getDelegate(followLinks: true).openSync(mode: mode));
 
   @override
-  Stream<Uint8List> openRead([int? start, int? end]) =>
-      getDelegate(followLinks: true).openRead(start, end).cast<Uint8List>();
+  Stream<List<int>> openRead([int? start, int? end]) =>
+      getDelegate(followLinks: true).openRead(start, end);
 
   @override
   IOSink openWrite({
diff --git a/packages/file/lib/src/backends/memory/memory_file.dart b/packages/file/lib/src/backends/memory/memory_file.dart
index c2a46f7..ba4faab 100644
--- a/packages/file/lib/src/backends/memory/memory_file.dart
+++ b/packages/file/lib/src/backends/memory/memory_file.dart
@@ -196,7 +196,7 @@
   }
 
   @override
-  Stream<Uint8List> openRead([int? start, int? end]) {
+  Stream<List<int>> openRead([int? start, int? end]) {
     fileSystem.opHandle(path, FileSystemOp.open);
     try {
       FileNode node = resolvedBacking as FileNode;
@@ -206,9 +206,9 @@
             ? content.sublist(start)
             : content.sublist(start, math.min(end, content.length));
       }
-      return Stream<Uint8List>.fromIterable(<Uint8List>[content]);
+      return Stream.value(content);
     } catch (e) {
-      return Stream<Uint8List>.fromFuture(Future<Uint8List>.error(e));
+      return Stream.error(e);
     }
   }
 
diff --git a/packages/file/pubspec.yaml b/packages/file/pubspec.yaml
index 09d6a5f..c4a8753 100644
--- a/packages/file/pubspec.yaml
+++ b/packages/file/pubspec.yaml
@@ -19,4 +19,6 @@
   test: ^1.23.1
 
 dependency_overrides:
-  glob: 2.1.1
\ No newline at end of file
+  # Temporary to break a dependency cycle.  See:
+  # <https://github.com/google/file.dart/pull/217#issuecomment-1530032688>
+  glob: 2.1.1
diff --git a/packages/file/test/common_tests.dart b/packages/file/test/common_tests.dart
index 22fb36f..6028c77 100644
--- a/packages/file/test/common_tests.dart
+++ b/packages/file/test/common_tests.dart
@@ -2273,6 +2273,21 @@
           expect(f, isNot(exists));
           expect(newFile, exists);
         });
+
+        test('openReadCompatibleWithUtf8Decoder', () async {
+          const content = 'Hello world!';
+          File file = fs.file(ns('/foo'))
+            ..createSync()
+            ..writeAsStringSync(content);
+          expect(
+            await file
+                .openRead()
+                .transform(utf8.decoder)
+                .transform(const LineSplitter())
+                .first,
+            content,
+          );
+        });
       });
 
       group('openWrite', () {