|
| 1 | +UE4 IO & Package介绍 |
| 2 | +=== |
| 3 | + |
| 4 | +* UPackage & FLinker & FArchive |
| 5 | +* BulkData |
| 6 | +* PlatformFile |
| 7 | +* NetworkFileSystem |
| 8 | + |
| 9 | +## 基础IO文件操作 |
| 10 | +--- |
| 11 | + |
| 12 | +- FileHelper (最简单的文件操作方式) |
| 13 | + |
| 14 | +``` cpp |
| 15 | +#include "Misc/FileHelper.h" |
| 16 | +FFileHelper::BufferToString( FString& Result, const uint8* Buffer, int32 Size ) |
| 17 | +FFileHelper::LoadFileToArray(TArray<uint8>& Result, const TCHAR* Filename, uint32 Flags = 0); |
| 18 | +FFileHelper::LoadFileToString( FString& Result, const TCHAR* Filename, EHashOptions VerifyFlags = EHashOptions::None, uint32 ReadFlags = 0 ); |
| 19 | +``` |
| 20 | +
|
| 21 | +- PlatformFile |
| 22 | +- IFileManager |
| 23 | +
|
| 24 | +``` cpp |
| 25 | +#include "HAL/FileManager.h" |
| 26 | +class IFileManager |
| 27 | +{ |
| 28 | +public: |
| 29 | + static IFileManager& Get(); |
| 30 | + FArchive* CreateFileReader( const TCHAR* Filename, uint32 ReadFlags=0 ); |
| 31 | + FArchive* CreateFileWriter( const TCHAR* Filename, uint32 WriteFlags=0 ); |
| 32 | + bool DirectoryExists( const TCHAR* InDirectory ); |
| 33 | + FDateTime GetAccessTimeStamp( const TCHAR* Filename ); |
| 34 | +}; |
| 35 | +``` |
| 36 | + |
| 37 | +- FPlatformFileManager 最复杂的文件读取方式 |
| 38 | + |
| 39 | +``` cpp |
| 40 | +#include "HAL/PlatformFileManager.h" |
| 41 | +class FPlatformFileManager { |
| 42 | +public: |
| 43 | + static FPlatformFileManager& Get(); |
| 44 | + // 创建 |
| 45 | + IPlatformFile* GetPlatformFile( const TCHAR* Name ); |
| 46 | + IPlatformFile& GetPlatformFile(); |
| 47 | +}; |
| 48 | +// 平台文件抽象类 |
| 49 | +class IPlatformFile { |
| 50 | +public: |
| 51 | +void InitializeNewAsyncIO(); |
| 52 | +IFileHandle* OpenRead(const TCHAR* Filename, bool bAllowWrite = false); |
| 53 | +IFileHandle* OpenReadNoBuffering(const TCHAR* Filename, bool bAllowWrite = false); |
| 54 | +IFileHandle* OpenWrite(const TCHAR* Filename, bool bAppend = false, bool bAllowRead = false); |
| 55 | +IAsyncReadFileHandle* OpenAsyncRead(const TCHAR* Filename); |
| 56 | +// 内存映射文件 |
| 57 | +IMappedFileHandle* OpenMapped(const TCHAR* Filename); |
| 58 | +IMappedFileHandle* AllocateMapped(const TCHAR* Filename, int64 Size); |
| 59 | +bool CopyDirectoryTree(const TCHAR* DestinationDirectory, const TCHAR* Source, bool bOverwriteAllExisting); |
| 60 | +}; |
| 61 | +``` |
| 62 | +
|
| 63 | +- BulkData 读取 |
| 64 | +``` cpp |
| 65 | +// BulkData (Size > 16K) |
| 66 | +class IAsyncReadRequest; |
| 67 | +typedef TFunction<void(bool bWasCancelled, IAsyncReadRequest*)> FAsyncFileCallBack; |
| 68 | +class FByteBulkData |
| 69 | +{ |
| 70 | +public: |
| 71 | +
|
| 72 | +GetFileName(); |
| 73 | +
|
| 74 | +FBulkDataIORequest* |
| 75 | + CreateStreamingRequest( |
| 76 | + EAsyncIOPriorityAndFlags Priority, |
| 77 | + FAsyncFileCallBack* CompleteCallback, |
| 78 | + uint8* UserSuppliedMemory) const; |
| 79 | +
|
| 80 | +FBulkDataIORequest* |
| 81 | + CreateStreamingRequest( |
| 82 | + int64 OffsetInBulkData, int64 BytesToRead, |
| 83 | + EAsyncIOPriorityAndFlags Priority, |
| 84 | + FAsyncFileCallBack* CompleteCallback, |
| 85 | + uint8* UserSuppliedMemory) const; |
| 86 | +}; |
| 87 | +
|
| 88 | +// 异步文件读取 |
| 89 | +IAsyncReadFileHandle* IORequestHandle = FPlatformFileManager::Get().GetPlatformFile().OpenAsyncRead(*Filename); |
| 90 | +check(IORequestHandle); // this generally cannot fail because it is async |
| 91 | +if (IORequestHandle == nullptr) |
| 92 | +{ |
| 93 | + return nullptr; |
| 94 | +} |
| 95 | +const int64 OffsetInFile = GetBulkDataOffsetInFile() + OffsetInBulkData; |
| 96 | +IAsyncReadRequest* ReadRequest = IORequestHandle->ReadRequest(OffsetInFile, BytesToRead, Priority, CompleteCallback, UserSuppliedMemory); |
| 97 | +if (ReadRequest != nullptr) |
| 98 | +{ |
| 99 | + return new FBulkDataIORequest(IORequestHandle, ReadRequest, BytesToRead); |
| 100 | +} |
| 101 | +else |
| 102 | +{ |
| 103 | + delete IORequestHandle; |
| 104 | + return nullptr; |
| 105 | +} |
| 106 | +
|
| 107 | +bool FBulkDataIORequest::PollCompletion() const |
| 108 | +{ |
| 109 | + return ReadRequest->PollCompletion(); |
| 110 | +} |
| 111 | +bool FBulkDataIORequest::WaitCompletion(float TimeLimitSeconds) const |
| 112 | +{ |
| 113 | + return ReadRequest->WaitCompletion(TimeLimitSeconds); |
| 114 | +} |
| 115 | +uint8* FBulkDataIORequest::GetReadResults() const |
| 116 | +{ |
| 117 | + return ReadRequest->GetReadResults(); |
| 118 | +} |
| 119 | +``` |
| 120 | + |
| 121 | +- MemoryMapping File(内存映射文件) |
| 122 | + |
| 123 | +```cpp |
| 124 | +check(!FPlatformProperties::GetMemoryMappingAlignment() || IsAligned(BulkDataOffsetInFile, FPlatformProperties::GetMemoryMappingAlignment())); |
| 125 | +bWasMapped = BulkData.MapFile(*Filename, BulkDataOffsetInFile, GetBulkDataSize()); |
| 126 | + |
| 127 | +bool FUntypedBulkData::FAllocatedPtr::MapFile(const TCHAR *InFilename, int64 Offset, int64 Size) |
| 128 | +{ |
| 129 | + check(!MappedHandle && !MappedRegion); // It doesn't make sense to do this twice, but if need be, not hard to do |
| 130 | + |
| 131 | + MappedHandle = FPlatformFileManager::Get().GetPlatformFile().OpenMapped(InFilename); |
| 132 | + |
| 133 | + if (!MappedHandle) |
| 134 | + { |
| 135 | + return false; |
| 136 | + } |
| 137 | + MappedRegion = MappedHandle->MapRegion(Offset, Size, true); //@todo we really don't want to hit the disk here to bring it into memory |
| 138 | + if (!MappedRegion) |
| 139 | + { |
| 140 | + delete MappedHandle; |
| 141 | + MappedHandle = nullptr; |
| 142 | + return false; |
| 143 | + } |
| 144 | + |
| 145 | + check(Size == MappedRegion->GetMappedSize()); |
| 146 | + Ptr = (void*)(MappedRegion->GetMappedPtr()); //@todo mapped files should probably be const-correct |
| 147 | + check(IsAligned(Ptr, FPlatformProperties::GetMemoryMappingAlignment())); |
| 148 | + bAllocated = true; |
| 149 | + return true; |
| 150 | +} |
| 151 | + |
| 152 | +void FUntypedBulkData::FAllocatedPtr::UnmapFile() |
| 153 | +{ |
| 154 | + if (MappedRegion || MappedHandle) |
| 155 | + { |
| 156 | + delete MappedRegion; |
| 157 | + delete MappedHandle; |
| 158 | + MappedRegion = nullptr; |
| 159 | + MappedHandle = nullptr; |
| 160 | + Ptr = nullptr; // make sure we don't try to free this pointer |
| 161 | + } |
| 162 | +} |
| 163 | +``` |
| 164 | +
|
| 165 | +- FArchive |
| 166 | +
|
| 167 | +```cpp |
| 168 | +class FArchive { |
| 169 | +public: |
| 170 | +FString GetArchiveName() const; |
| 171 | +FLinker* GetLinker(); |
| 172 | +
|
| 173 | +int64 TotalSize(); |
| 174 | +bool AtEnd(); |
| 175 | +void Seek(int64 InPos); |
| 176 | +int64 Tell(); |
| 177 | +void Flush(); |
| 178 | +
|
| 179 | +void Serialize(void* V, int64 Length); |
| 180 | +FArchive& ByteOrderSerialize(void* V, int32 Length); |
| 181 | +
|
| 182 | +bool SetCompressionMap(TArray<struct FCompressedChunk>* CompressedChunks, ECompressionFlags CompressionFlags); |
| 183 | +void SerializeCompressed(void* V, int64 Length, FName CompressionFormat, ECompressionFlags Flags=COMPRESS_NoFlags, bool bTreatBufferAsFileReader=false); |
| 184 | +
|
| 185 | +void AttachBulkData(UObject* Owner, FUntypedBulkData* BulkData); |
| 186 | +void DetachBulkData(FUntypedBulkData* BulkData, bool bEnsureBulkDataIsLoaded); |
| 187 | +
|
| 188 | +//版本管理 |
| 189 | +int32 UE4Ver() const; |
| 190 | +FEngineVersionBase EngineVer() const; |
| 191 | +int32 CustomVer(const struct FGuid& Key) const; |
| 192 | +void UsingCustomVersion(const struct FGuid& Guid); |
| 193 | +
|
| 194 | +private: |
| 195 | +// 自定义版本 |
| 196 | +mutable FCustomVersionContainer* CustomVersionContainer = nullptr; |
| 197 | +}; |
| 198 | +``` |
| 199 | + |
| 200 | +--- |
| 201 | + |
| 202 | +## UPackage结构 |
| 203 | + |
| 204 | +## DirectStorage |
| 205 | + |
| 206 | +- Queue IO Request |
| 207 | + |
| 208 | +``` cpp |
| 209 | +QueueReuest(DestMemoryAddress, FileName) |
| 210 | +QueueSignal(Fence) |
| 211 | +``` |
0 commit comments