TMap object into TFile

HEllo,

I think TMap is interesting to manipulate. I have a std::map<TString, TString> that I would like to convert into a TMap, save it into a root file (possibly not at the root of the file), and retrieve it later on.

Could you advice on this ?

Here is what I have done so far, but the TMap object is split into separate keys when saved into a root file. ( I guess this is somehow expected? Read TMap from a file, @pcanal, @eguiraud would you maybe have an idea ?)

TFile *f = TFile::Open("test.root", "recreate");
TMap *m = new TMap();

m->Add(new TObjString("test:0"), TObjString("My Test 0"));
m->Add(new TObjString("test:1"), TObjString("My Test 1"));

m->Write();
f->Close();

Opening the saved file is returning this list, but I would like to store it as a single object.

Collection name='THashList', class='THashList', size=4
 TKey Name = test:0, Title = Collectable string class, Cycle = 1
 TKey Name = My Test 0, Title = Collectable string class, Cycle = 1
 TKey Name = test:1, Title = Collectable string class, Cycle = 1
 TKey Name = My Test 1, Title = Collectable string class, Cycle = 1

Dear @meyerma ,

If you already have a std::map, you could write that directly to your file:

#include <iostream>
#include <map>
#include <string>

#include <TFile.h>

int main()
{
   std::map<std::string, std::string> mymap{{"a", "A"}, {"b", "B"}, {"c", "C"}};

   {
      TFile f{"myfile.root", "recreate"};
      f.WriteObject(&mymap, "mymap");
   }

   {
      TFile f{"myfile.root"};
      auto *mymap = f.Get<std::map<std::string, std::string>>("mymap");
      for (const auto &kv : *mymap) {
         std::cout << kv.first << ": " << kv.second << std::endl;
      }
   }
}

Does this serve your purpose better maybe?

Cheers,
Vincenzo

1 Like

Definitely :slight_smile: is that possible to do the same with any object or just map ?

Sure, ROOT I/O supports writing arbitrary C++ objects to TFile!
For many standard C++ classes, you can use my example from above and just change std::map to the corresponding class.

You can also define your own custom C++ class and write such objects to file, you need a bit more work to generate information for ROOT to know how to write your class to the file. This is known as creating a class dictionary, see I/O of custom classes - ROOT and GitHub - eguiraud/root_dictionaries_tutorial: A tutorial on creating ROOT dictionaries to perform I/O of custom C++ classes for more info for this specific case

Best,
Vincenzo

1 Like

I was used to add my custom class, but all of them inherits from TObject/TNamed. I was assuming this was kind of mandatory.

I will check how vector of TObject are handled, because I would not like to have some randomly located object appearing in the root of my TFile

Also for the record:

but the TMap object is split into separate keys

is solved by

m->Write(nullptr, TObject::kSingleKey, nullptr);
1 Like

This is exactly what I needed ! I ended up using kSingleKey (altought I cannot browse with TBrowser because my map is too big :sweat_smile:

Just a side comment, this works better when using compiled ROOT programs
m->Write(nullptr, TObject::kSingleKey, 0);

Thank you so much guys, this was very fruitful discussion…
M.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.