Mantid
Loading...
Searching...
No Matches
BinaryFile.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#pragma once
8
9#include "MantidKernel/DllConfig.h"
10
11#include <filesystem>
12#include <fstream>
13#include <memory>
14#include <string>
15#include <vector>
16
17namespace Mantid {
18namespace Kernel {
19
21constexpr size_t DEFAULT_BLOCK_SIZE{100000}; // 100,000
22
24constexpr size_t MAX_BLOCK_SIZE{100000000}; // 100 million
25
27constexpr size_t MIN_BLOCK_SIZE{1000};
28
43template <typename T> class DLLExport BinaryFile {
44public:
45 //------------------------------------------------------------------------------------
47 BinaryFile() : handle(nullptr), num_elements(0), offset(0) {}
48
49 //------------------------------------------------------------------------------------
51 BinaryFile(std::filesystem::path const &filepath) { this->open(filepath); }
52
54 ~BinaryFile() { this->close(); }
55
56 //------------------------------------------------------------------------------------
63 void open(std::filesystem::path const &filepath) {
64 this->handle.reset(nullptr);
65 if (!std::filesystem::exists(filepath)) {
66 throw std::invalid_argument(std::string("BinaryFile::open \"") + filepath.string() + "\" was not found.");
67 }
68 // Open the file
69 this->handle = std::make_unique<std::ifstream>(filepath, std::ios::binary);
70 // Count the # of elements.
71 this->num_elements = this->getFileSize();
72 // Make sure we are starting at 0
73 this->offset = 0;
74 }
75
76 //------------------------------------------------------------------------------------
79 void close() { handle.reset(nullptr); }
80
81 //-----------------------------------------------------------------------------
83 size_t getNumElements() const { return this->num_elements; }
84
86 size_t getOffset() const { return this->offset; }
87
88 //-----------------------------------------------------------------------------
93 size_t getBufferSize(const size_t num_items) const {
94 if (num_items < DEFAULT_BLOCK_SIZE)
95 return num_items;
96 else
97 return DEFAULT_BLOCK_SIZE;
98 }
99
100 //-----------------------------------------------------------------------------
106 std::vector<T> loadAll() {
107 if (!handle) {
108 throw std::runtime_error("BinaryFile: file is not open.");
109 }
110
111 // Initialize the pointer
112 std::vector<T> data;
113
114 // A buffer to load from
115 size_t buffer_size = getBufferSize(num_elements);
116 auto buffer = std::make_unique<T[]>(buffer_size);
117
118 // Make sure we are at the beginning
119 offset = 0;
120 handle->seekg(0, std::ios::beg);
121
122 while (offset < num_elements) {
123 // Load that block of data
124 const auto loaded_size = loadBlock(buffer.get(), buffer_size);
125 // Insert into the data
126 data.insert(data.end(), buffer.get(), std::next(buffer.get(), loaded_size));
127 }
128
129 // Close the file, since we are done.
130 this->close();
131
132 // Here's your vector!
133 return data;
134 }
135
136 //-----------------------------------------------------------------------------
142 std::vector<T> loadAllIntoVector() {
143 if (!handle) {
144 throw std::runtime_error("BinaryFile: file is not open.");
145 }
146 std::vector<T> data;
147
148 // A buffer to load from
149 size_t buffer_size = getBufferSize(num_elements);
150 auto buffer = new T[buffer_size];
151
152 // Make sure we are at the beginning
153 offset = 0;
154 handle->seekg(0, std::ios::beg);
155
156 while (offset < num_elements) {
157 // Load that block of data
158 const auto loaded_size = loadBlock(buffer, buffer_size);
159 // Insert into the data
160 data.insert(data.end(), buffer, (buffer + loaded_size));
161 }
162
163 // Close the file, since we are done.
164 this->close();
165 // Free memory
166 delete[] buffer;
167
168 return data;
169 }
170
171 //-----------------------------------------------------------------------------
183 size_t loadBlock(T *buffer, size_t block_size) {
184 if (!handle) {
185 throw std::runtime_error("BinaryFile: file is not open.");
186 }
187
188 size_t loaded_size;
189 // Limit how much is loaded
190 loaded_size = block_size;
191 if (offset + loaded_size > num_elements)
192 loaded_size = num_elements - offset;
193 // Read it right into the buffer
194 handle->read(reinterpret_cast<char *>(buffer), loaded_size * obj_size);
195 offset += loaded_size;
196 return loaded_size;
197 }
198
199 //-----------------------------------------------------------------------------
212 size_t loadBlockAt(T *buffer, size_t newOffset, size_t block_size) {
213 if (!handle) {
214 throw std::runtime_error("BinaryFile: file is not open.");
215 }
216 // Change our offset to the new spot.
217 offset = newOffset;
218 handle->seekg(sizeof(T) * offset, std::ios::beg);
219 return loadBlock(buffer, block_size);
220 }
221
222private:
228 size_t getFileSize() {
229 this->obj_size = sizeof(T);
230
231 if (!handle) {
232 throw std::runtime_error("BinaryFile::getFileSize: Cannot find the size "
233 "of a file from a null handle");
234 }
235
236 // get the size of the file in bytes and reset the handle back to the
237 // beginning
238 handle->seekg(0, std::ios::end);
239 size_t filesize = static_cast<size_t>(handle->tellg());
240 handle->seekg(0, std::ios::beg);
241
242 // check the file is a compatible size
243 if (filesize % obj_size != 0) {
244 std::stringstream msg;
245 msg << "BinaryFile::getFileSize: File size is not compatible with data "
246 "size ";
247 msg << filesize << "%" << obj_size << "=";
248 msg << filesize % obj_size;
249 throw std::runtime_error(msg.str());
250 }
251
252 return filesize / sizeof(T);
253 }
254
256 std::unique_ptr<std::ifstream> handle;
258 size_t obj_size;
262 size_t offset;
263};
264
265} // Namespace Kernel
266
267} // Namespace Mantid
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
Definition System.h:37
The BinaryFile template is a helper function for loading simple binary files.
Definition BinaryFile.h:43
BinaryFile(std::filesystem::path const &filepath)
Constructor - open a file.
Definition BinaryFile.h:51
size_t getFileSize()
Get the size of a file as a multiple of a particular data type.
Definition BinaryFile.h:228
size_t loadBlock(T *buffer, size_t block_size)
Loads a single block from file and returns a pointer to a vector containing it.
Definition BinaryFile.h:183
size_t obj_size
Size of each object.
Definition BinaryFile.h:258
size_t getNumElements() const
Returns the # of elements in the file (cached result of getFileSize)
Definition BinaryFile.h:83
BinaryFile()
Empty constructor.
Definition BinaryFile.h:47
std::unique_ptr< std::ifstream > handle
File stream.
Definition BinaryFile.h:256
size_t offset
Offset into the file, if loading in blocks.
Definition BinaryFile.h:262
size_t getOffset() const
Returns the current offset into the file.
Definition BinaryFile.h:86
size_t loadBlockAt(T *buffer, size_t newOffset, size_t block_size)
Loads a single block from file and returns a pointer to a vector containing it.
Definition BinaryFile.h:212
std::vector< T > loadAll()
Loads the entire contents of the file into a pointer to a std::vector.
Definition BinaryFile.h:106
void close()
Close the file.
Definition BinaryFile.h:79
~BinaryFile()
Destructor, close the file if needed.
Definition BinaryFile.h:54
size_t num_elements
Number of elements of size T in the file.
Definition BinaryFile.h:260
void open(std::filesystem::path const &filepath)
Open a file and keep a handle to the file.
Definition BinaryFile.h:63
size_t getBufferSize(const size_t num_items) const
Get a buffer size for loading blocks of data.
Definition BinaryFile.h:93
std::vector< T > loadAllIntoVector()
Loads the entire contents of the file into a std::vector.
Definition BinaryFile.h:142
constexpr size_t MIN_BLOCK_SIZE
Min size of a block (too small is inefficient)
Definition BinaryFile.h:27
constexpr size_t DEFAULT_BLOCK_SIZE
Default number of items to read in from any of the files.
Definition BinaryFile.h:21
constexpr size_t MAX_BLOCK_SIZE
Max size block to read from a file (memory limitations)
Definition BinaryFile.h:24
Helper class which provides the Collimation Length for SANS instruments.