Agrarsense
CSVFile.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 FrostBit Software Lab at the Lapland University of Applied Sciences
2//
3// This work is licensed under the terms of the MIT license.
4// For a copy, see <https://opensource.org/licenses/MIT>.
5
6#include "CSVFile.h"
7
10
11#include "Misc/Paths.h"
12#include "HAL/PlatformFileManager.h"
13#include "GenericPlatform/GenericPlatformFile.h"
14
15UCSVFile* UCSVFile::CreateCSVFile(const FString& FileNameWithoutExtension, const FCSVFileSettings& Settings)
16{
17 UCSVFile* CSVFile = NewObject<UCSVFile>(UCSVFile::StaticClass());
18 CSVFile->AddToRoot();
19 if (CSVFile)
20 {
21 CSVFile->Create(FileNameWithoutExtension, Settings);
22 }
23 return CSVFile;
24}
25
26void UCSVFile::Create(const FString& FileNameWithoutExtension, const FCSVFileSettings& Settings)
27{
28 CurrentSettings = Settings;
29
30 // Simulator data directory for this run. Returns SIMULATOR_ROOT/Data/Run_{NUM}
31 FString DataDirectory = UAgrarsensePaths::GetDataFolder();
32
33 FString BasePath = Settings.CustomPath.IsEmpty() ? DataDirectory + "/CSV/" : Settings.CustomPath;
34 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
35 if (!PlatformFile.DirectoryExists(*BasePath))
36 {
37 PlatformFile.CreateDirectoryTree(*BasePath);
38 }
39
40 FString FullPath = FPaths::Combine(*BasePath, FileNameWithoutExtension + TEXT(".csv"));
41 UE_LOG(LogTemp, Warning, TEXT("FullPath: %s"), *FullPath);
42
43 if (Settings.CreateUnique)
44 {
45 int32 Counter = 0;
46 while (FPaths::FileExists(FullPath))
47 {
48 FullPath = FPaths::Combine(*BasePath, FileNameWithoutExtension + FString::Printf(TEXT("_%d.csv"), Counter++));
49 }
50 }
51
53 {
54 PendingRows.Reserve(Settings.QueueSize);
55 }
56
57 FilePath = FullPath;
58
59 OpenStream();
60}
61
63{
64 if (CSVStream.is_open())
65 {
66 CSVStream.close();
67 }
68
69 std::ios_base::openmode Mode = std::ios::out;
71 {
72 Mode |= std::ios::app;
73 }
74
75 CSVStream.open(TCHAR_TO_UTF8(*FilePath), Mode);
76}
77
78void UCSVFile::WriteRow(const TArray<FString>& Cells)
79{
80 if (!CSVStream.is_open()) OpenStream();
81 if (!CSVStream.is_open()) return;
82
83 // Determine delimiter
84 FString Delimiter = TEXT(",");
86 {
87 Delimiter = TEXT(";");
88 }
90 {
91 Delimiter = TEXT("\t");
92 }
93
94 // Join values using chosen delimiter
95 FString Line = FString::Join(Cells, *Delimiter);
96
98 {
99 WriteRaw(Line); // Write the line immediately
100 }
102 {
103 // Queue the line for later
104 PendingRows.Add(Line);
105 }
106}
107
108void UCSVFile::WriteRaw(const FString& Line)
109{
110 if (!CSVStream.is_open()) OpenStream();
111 if (!CSVStream.is_open()) return;
112
113 CSVStream << TCHAR_TO_UTF8(*Line) << std::endl;
114}
115
117{
118 if (CSVStream.is_open())
119 {
120 // If we have queued rows, write them out
122 {
123 for (const FString& Row : PendingRows)
124 {
125 WriteRaw(Row);
126 }
127 PendingRows.Empty();
128 }
129
130 CSVStream.close();
131 }
132}
133
135{
136 Close();
137 ConditionalBeginDestroy();
138}
static FString GetDataFolder()
static UCSVFile * CreateCSVFile(const FString &FileNameWithoutExtension, const FCSVFileSettings &Settings)
Definition: CSVFile.cpp:15
void WriteRaw(const FString &Line)
Definition: CSVFile.cpp:108
std::ofstream CSVStream
Definition: CSVFile.h:92
void Create(const FString &FileNameWithoutExtension, const FCSVFileSettings &Settings)
Definition: CSVFile.cpp:26
FString FilePath
Definition: CSVFile.h:88
TArray< FString > PendingRows
Definition: CSVFile.h:86
void Close()
Definition: CSVFile.cpp:116
void OpenStream()
Definition: CSVFile.cpp:62
FCSVFileSettings CurrentSettings
Definition: CSVFile.h:90
void WriteRow(const TArray< FString > &Cells)
Definition: CSVFile.cpp:78
void Destroy()
Definition: CSVFile.cpp:134
bool CreateUnique
Definition: CSVFile.h:42
ECSVDelimiter Delimiter
Definition: CSVFile.h:36
int32 QueueSize
Definition: CSVFile.h:48
FString CustomPath
Definition: CSVFile.h:51
FCSVFileWriteOptions FileWriteOption
Definition: CSVFile.h:45