From 5cbe37133d591b6eec4d686794ac61db72116742 Mon Sep 17 00:00:00 2001 From: Florian Uhlig <f.uhlig@gsi.de> Date: Tue, 19 Jan 2021 15:22:55 +0100 Subject: [PATCH] Add function which checks if an input is a ROOT file The function Cbm::File::IsRootFile checks if a file with the given name exists and if this is confirmed it checks if the file is either a ROOT file or a ROOT file stored in a ZIP file. ROOT is able to handle ROOT files stored in a ZIP archive. The function returns true when the file is a ROOT file and false in any other case. --- core/base/CMakeLists.txt | 1 + core/base/CbmBaseLinkDef.h | 2 + core/base/utils/CbmFileUtils.cxx | 93 ++++++++++++++++++++++++++++++++ core/base/utils/CbmFileUtils.h | 17 ++++++ 4 files changed, 113 insertions(+) create mode 100644 core/base/utils/CbmFileUtils.cxx create mode 100644 core/base/utils/CbmFileUtils.h diff --git a/core/base/CMakeLists.txt b/core/base/CMakeLists.txt index 23d40aeb04..b67dbdd8c2 100644 --- a/core/base/CMakeLists.txt +++ b/core/base/CMakeLists.txt @@ -57,6 +57,7 @@ report/CbmLatexReportElement.cxx utils/CbmUtils.cxx utils/CbmGeometryUtils.cxx utils/CbmMediaList.cxx +utils/CbmFileUtils.cxx ) Set(LINKDEF CbmBaseLinkDef.h) diff --git a/core/base/CbmBaseLinkDef.h b/core/base/CbmBaseLinkDef.h index d80e17ee00..d8365ddd8a 100644 --- a/core/base/CbmBaseLinkDef.h +++ b/core/base/CbmBaseLinkDef.h @@ -73,4 +73,6 @@ // can not read the file with the CbmMediaList object. For other platforms there is no // problem without the line. So generate the correct streamer info in any way. #pragma link C++ class std::pair < TString, TString>; + +#pragma link C++ function Cbm::File::IsRootFile( string ); #endif diff --git a/core/base/utils/CbmFileUtils.cxx b/core/base/utils/CbmFileUtils.cxx new file mode 100644 index 0000000000..60af49a0d1 --- /dev/null +++ b/core/base/utils/CbmFileUtils.cxx @@ -0,0 +1,93 @@ +#include "CbmFileUtils.h" + +#include "FairLogger.h" // for LOG, info and error + +#include "TArchiveFile.h" // for TArchiveFile +#include "TFile.h" // for TFile +#include "TObjArray.h" + +#include <string> // for string, find, substr +#include <sys/stat.h> // for stcuct stat + + +namespace Cbm { + namespace File { + bool IsRootFile(std::string filename) { + // Currently plain root files and root files stored in a zip file are supported. + // The destiction between the two is a "#" in the filename string which separates the + // name of the zip file from the name of the root file which is inside the zip file. + // In case the filename contains a hash (e.g. multi.zip#file.root) the hash + // separates the name of a zipfile (multi.zip) which contains the real root file + // (file.root). + // This nameing convention (e.g. multi.zip#file.root) is sed by ROOT. + + // If a filename string contains a hash "#" + // split the string at the # in the name of the zipfile and + // the name of the contained root file. + std::string checkFilename {""}; + std::string membername {""}; + std::size_t found = filename.find("#"); + if (found != std::string::npos) { + checkFilename = filename.substr(0, found); + membername = filename.substr(found + 1); + } else { + checkFilename = filename; + } + + bool wasfound = kFALSE; + + // Check if the file exist + // In case of a root file contained in a zip archive check if the zip file + // exist + struct stat buffer; + if (stat(checkFilename.c_str(), &buffer) == 0) { + wasfound = kTRUE; + } else { + wasfound = kFALSE; + LOG(error) << "Input File " << checkFilename << " not found"; + } + + // In case of a zip archive check if the archive contains the root file + if (membername.compare("") != 0) { + TFile* fzip = TFile::Open(checkFilename.c_str()); + if (fzip->IsOpen()) { + TArchiveFile* archive = fzip->GetArchive(); + if (archive) { + TObjArray* members = archive->GetMembers(); + if (members->FindObject(membername.c_str()) == 0) { + LOG(error) << "File " << membername << " not found in zipfile " + << checkFilename; + wasfound = kFALSE; + } else { + LOG(info) << "File " << membername << " found in zipfile " + << checkFilename; + wasfound = kTRUE; + } + } else { + LOG(error) << "Zipfile " << checkFilename + << " does not contain an archive"; + wasfound = kFALSE; + } + fzip->Close(); + delete fzip; + } else { + LOG(error) << "Could not open zipfile " << checkFilename; + wasfound = kFALSE; + } + } else { + TFile* rootfile = TFile::Open(checkFilename.c_str()); + if (rootfile->IsOpen()) { + LOG(info) << "File " << checkFilename << " is a ROOT file."; + wasfound = kTRUE; + } else { + LOG(error) << "File " << checkFilename << " is no ROOT file."; + wasfound = kFALSE; + } + rootfile->Close(); + delete rootfile; + } + + return wasfound; + } + } // namespace File +} // namespace Cbm diff --git a/core/base/utils/CbmFileUtils.h b/core/base/utils/CbmFileUtils.h new file mode 100644 index 0000000000..01f14589c5 --- /dev/null +++ b/core/base/utils/CbmFileUtils.h @@ -0,0 +1,17 @@ +#ifndef CBMFILEUTILS_H_ +#define CBMFILEUTILS_H_ + +#include <string> // for string + +namespace Cbm { + namespace File { + /** + * \brief Check if a the file exist and is a root file + * \param[in] filename The filename of the file to be checked + * \value true if file is an existing root file, 0 in any other case + **/ + bool IsRootFile(std::string filename); + } //namespace File +} // namespace Cbm + +#endif /* CBMFILEUTILS_H_ */ -- GitLab