-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a simple FileDescriptor class that wraps a file stream
The stream is open for as long as the object is alive. Refs #7263 FileDescriptor uses streams rather than c file handles. Refs #7263
- Loading branch information
1 parent
b846d13
commit 8681dff
Showing
4 changed files
with
261 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
Code/Mantid/Framework/Kernel/inc/MantidKernel/FileDescriptor.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#ifndef MANTID_KERNEL_FILEDESCRIPTOR_H_ | ||
#define MANTID_KERNEL_FILEDESCRIPTOR_H_ | ||
|
||
#include "MantidKernel/ClassMacros.h" | ||
#include "MantidKernel/DllConfig.h" | ||
|
||
#include <fstream> | ||
#include <string> | ||
|
||
namespace Mantid | ||
{ | ||
namespace Kernel | ||
{ | ||
|
||
/** | ||
Defines a wrapper around an open file. Details of the file such as the filename & extension can be queried. | ||
The file is closed when the object is destroyed. | ||
The object stores an opened fstream object that can be accessed using the data() method. | ||
Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory | ||
This file is part of Mantid. | ||
Mantid is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 3 of the License, or | ||
(at your option) any later version. | ||
Mantid is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
File change history is stored at: <https://github.com/mantidproject/mantid> | ||
Code Documentation is available at: <http://doxygen.mantidproject.org> | ||
*/ | ||
class MANTID_KERNEL_DLL FileDescriptor | ||
{ | ||
public: | ||
/// Constructor accepting a filename | ||
FileDescriptor(const std::string & filename); | ||
/// Destructor | ||
~FileDescriptor(); | ||
|
||
/** | ||
* Access the filename | ||
* @returns A reference to a const string containing the filename | ||
*/ | ||
inline const std::string & filename() const { return m_filename; } | ||
/** | ||
* Access the file extension. Defined as the string after and including the last period character | ||
* @returns A reference to a const string containing the file extension | ||
*/ | ||
inline const std::string & extension() const { return m_extension; } | ||
/** | ||
* Access the open file stream. DO NOT CLOSE IT | ||
* @returns The current stream | ||
*/ | ||
inline std::ifstream & data() { return m_file; } | ||
|
||
/// Reset the file stream to the start of the file | ||
void resetStreamToStart(); | ||
|
||
private: | ||
DISABLE_DEFAULT_CONSTRUCT(FileDescriptor); | ||
DISABLE_COPY_AND_ASSIGN(FileDescriptor); | ||
|
||
/// Open the file and cache description elements | ||
void initialize(const std::string & filename); | ||
|
||
/// Full filename | ||
std::string m_filename; | ||
/// Extension | ||
std::string m_extension; | ||
/// Open file stream | ||
std::ifstream m_file; | ||
}; | ||
|
||
|
||
} // namespace Kernel | ||
} // namespace Mantid | ||
|
||
#endif /* MANTID_KERNEL_FILEDESCRIPTOR_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#include "MantidKernel/FileDescriptor.h" | ||
#include "MantidKernel/Exception.h" | ||
|
||
#include <Poco/File.h> | ||
#include <Poco/Path.h> | ||
|
||
namespace Mantid | ||
{ | ||
namespace Kernel | ||
{ | ||
//---------------------------------------------------------------------------------------------- | ||
// Public methods | ||
//---------------------------------------------------------------------------------------------- | ||
|
||
/** | ||
* @param filename A string containing a filename. The file must exist | ||
* @throws std::invalid_argument if the filename is empty or the file does not exist | ||
*/ | ||
FileDescriptor::FileDescriptor(const std::string & filename) : | ||
m_filename(), m_extension(), m_file(NULL) | ||
{ | ||
if(filename.empty()) | ||
{ | ||
throw std::invalid_argument("FileDescriptor() - Empty filename '" + filename + "'"); | ||
} | ||
if(!Poco::File(filename).exists()) | ||
{ | ||
throw std::invalid_argument("FileDescriptor() - File '" + filename + "' does not exist"); | ||
} | ||
initialize(filename); | ||
} | ||
|
||
/** | ||
* Closes the file handle | ||
*/ | ||
FileDescriptor::~FileDescriptor() | ||
{ | ||
m_file.close(); | ||
} | ||
|
||
/** | ||
* Moves the stream pointer back to the start of the file, without | ||
* reopening the file. Note that this will affect the stream that | ||
* has been accessed using the stream() method | ||
*/ | ||
void FileDescriptor::resetStreamToStart() | ||
{ | ||
m_file.seekg(0); | ||
} | ||
|
||
//---------------------------------------------------------------------------------------------- | ||
// Private methods | ||
//---------------------------------------------------------------------------------------------- | ||
|
||
/** | ||
* Set the description fields and opens the file | ||
* @param filename A string pointing to an existing file | ||
*/ | ||
void FileDescriptor::initialize(const std::string& filename) | ||
{ | ||
m_filename = filename; | ||
m_extension = "." + Poco::Path(filename).getExtension(); | ||
|
||
m_file.open(m_filename.c_str(), std::ios::in | std::ios::binary); | ||
if(!m_file) throw std::runtime_error("FileDescriptor::initialize - Cannot open file '" + filename + "' for reading"); | ||
} | ||
|
||
} // namespace Kernel | ||
} // namespace Mantid |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#ifndef MANTID_KERNEL_FILEDESCRIPTORTEST_H_ | ||
#define MANTID_KERNEL_FILEDESCRIPTORTEST_H_ | ||
|
||
#include <cxxtest/TestSuite.h> | ||
|
||
#include "MantidKernel/FileDescriptor.h" | ||
#include "MantidKernel/ConfigService.h" | ||
|
||
#include <Poco/Path.h> | ||
#include <Poco/File.h> | ||
|
||
using Mantid::Kernel::FileDescriptor; | ||
|
||
class FileDescriptorTest : public CxxTest::TestSuite | ||
{ | ||
public: | ||
// This pair of boilerplate methods prevent the suite being created statically | ||
// This means the constructor isn't called when running other tests | ||
static FileDescriptorTest *createSuite() { return new FileDescriptorTest(); } | ||
static void destroySuite( FileDescriptorTest *suite ) { delete suite; } | ||
|
||
FileDescriptorTest() | ||
{ | ||
using Mantid::Kernel::ConfigService; | ||
auto dataPaths = ConfigService::Instance().getDataSearchDirs(); | ||
for(auto it = dataPaths.begin(); it != dataPaths.end(); ++it) | ||
{ | ||
Poco::Path nxsPath(*it, "CNCS_7860_event.nxs"); | ||
if(Poco::File(nxsPath).exists()) m_testNexusPath = nxsPath.toString(); | ||
Poco::Path nonNxsPath(*it, "CSP79590.raw"); | ||
if(Poco::File(nonNxsPath).exists()) m_testNonNexusPath = nonNxsPath.toString(); | ||
|
||
if(!m_testNexusPath.empty() && !m_testNonNexusPath.empty()) break; | ||
} | ||
if(m_testNexusPath.empty() || m_testNonNexusPath.empty()) | ||
{ | ||
throw std::runtime_error("Unable to find test files for FileDescriptorTest. " | ||
"The AutoTestData directory needs to be in the search path"); | ||
} | ||
} | ||
|
||
//===================== Success cases ============================================ | ||
void test_Constructor_With_Existing_File_Initializes_Description_Fields() | ||
{ | ||
const std::string filename = m_testNexusPath; | ||
FileDescriptor descr(filename); | ||
|
||
TS_ASSERT_EQUALS(filename, descr.filename()); | ||
TS_ASSERT_EQUALS(".nxs", descr.extension()); | ||
} | ||
|
||
void test_File_Is_Opened_After_Object_Is_Constructed() | ||
{ | ||
FileDescriptor descr(m_testNexusPath); | ||
TS_ASSERT(descr.data().is_open()); | ||
} | ||
|
||
void test_Intial_Stream_Is_Positioned_At_Start_Of_File() | ||
{ | ||
const std::string filename = m_testNexusPath; | ||
FileDescriptor descr(filename); | ||
|
||
auto & stream = descr.data(); | ||
long int streamPos = stream.tellg(); | ||
|
||
TS_ASSERT_EQUALS(0, streamPos); | ||
} | ||
|
||
void test_ResetStreamToStart_Repositions_Stream_Start_Of_File() | ||
{ | ||
const std::string filename = m_testNexusPath; | ||
FileDescriptor descr(filename); | ||
auto & stream = descr.data(); | ||
char byte('0'); | ||
stream >> byte; // read byte from stream | ||
|
||
TS_ASSERT_EQUALS(1, stream.tellg()); | ||
descr.resetStreamToStart(); | ||
TS_ASSERT_EQUALS(0, stream.tellg()); | ||
} | ||
|
||
//===================== Failure cases ============================================ | ||
void test_Constructor_Throws_With_Empty_filename() | ||
{ | ||
TS_ASSERT_THROWS(FileDescriptor(""), std::invalid_argument); | ||
} | ||
|
||
void test_Constructor_Throws_With_NonExistant_filename() | ||
{ | ||
TS_ASSERT_THROWS(FileDescriptor("__ThisShouldBeANonExistantFile.txt"), std::invalid_argument); | ||
} | ||
|
||
private: | ||
std::string m_testNexusPath; | ||
std::string m_testNonNexusPath; | ||
}; | ||
|
||
|
||
#endif /* MANTID_KERNEL_FILEDESCRIPTORTEST_H_ */ |