I have a UTF-8 text file which starts with this line:

```
<HEAD><META name=GENERATOR content="MSHTML 10.00.9200.16521"><body>

```

When I read this file with `TFile.ReadAllText` with TEncoding.UTF8:

```
MyStr := TFile.ReadAllText(ThisFileNamePath, TEncoding.UTF8);

```

then the first 3 characters of the text file are omitted, so MyStr results in:

```
'AD><META name=GENERATOR content="MSHTML 10.00.9200.16521"><body>...'

```

However, when I read this file with `TFile.ReadAllText` without TEncoding.UTF8:

```
MyStr := TFile.ReadAllText(ThisFileNamePath);

```

then the file is read completely and correctly:

```
<HEAD><META name=GENERATOR content="MSHTML 10.00.9200.16521"><body>...

```

Does `TFile.ReadAllText` have a bug?
['https://Stackoverflow.com/questions/17133430', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1580348/']
The first three bytes are skipped because the RTL code assumes that the file contains a UTF-8 BOM. Clearly your file does not. 

The `TUTF8Encoding` class implements a `GetPreamble` method that specifies the `UTF-8` BOM. And `ReadAllBytes` skips the preamble specified by the encoding that you pass.

One simple solution would be to read the file into a byte array and then use `TEncoding.UTF8.GetString` to decode it into a string.

```
var
  Bytes: TBytes;
  Str: string;
....
Bytes := TFile.ReadAllBytes(FileName);
Str := TEncoding.UTF8.GetString(Bytes);

```

An more comprehensive alternative would be to make a `TEncoding` instance that ignored the UTF-8 BOM.

```
type
  TUTF8EncodingWithoutBOM = class(TUTF8Encoding)
  public
    function Clone: TEncoding; override;
    function GetPreamble: TBytes; override;
  end;

function TUTF8EncodingWithoutBOM.Clone: TEncoding;
begin
  Result := TUTF8EncodingWithoutBOM.Create;
end;

function TUTF8EncodingWithoutBOM.GetPreamble: TBytes;
begin
  Result := nil;
end;

```

Instantiate one of these (you only need one instance per process) and pass it to `TFile.ReadAllText`.

The advantage of using a singleton instance of `TUTF8EncodingWithoutBOM` is that you can use it anywhere that expects a `TEncoding`.
Actually the value you pass to ReadAllText is not the Default Encoding (when you check how it's implemented), it's an enforced encoding if you pass something other than Nil. Internally it calls other method of TEncoding that does have an extra default encoding parameter (for when the foundEncoding var parameter is set to nil and no encoding could be detected)

I was trying to make methods to work with Stream, based on the TFile.ReadAllText code and ended up with this, note the "DefaultEncoding=nil" (=nil so that no extra overloaded method needed) I use and the "ForceDefaultEncoding=false" (to say we always want to use that encoding)

```
function ReadAllBytes(const Stream: TStream): TBytes;
begin
  var LFileSize := Stream.Size;
  {$IFDEF CPU32BITS}
  if LFileSize > MaxInt then
    raise EInOutError.CreateRes(@SFileTooLong);
  {$ENDIF}
  SetLength(Result, LFileSize);
  Stream.ReadBuffer(result, Length(result));
end;

function ReadAllText(const Stream: TStream; const DefaultEncoding: TEncoding = nil; const ForceDefaultEncoding: Boolean = false): string;
var FoundEncoding: TEncoding;
begin
  if ForceDefaultEncoding then
    FoundEncoding := DefaultEncoding;
  var Buff := ReadAllBytes(Stream);
  var BOMLength := TEncoding.GetBufferEncoding(Buff, FoundEncoding, DefaultEncoding);
  result := FoundEncoding.GetString(Buff, BOMLength, Length(Buff) - BOMLength);
end;

```