Reading from a tree and writing to another tree


the following program is supposed to read all objects from directory ‘dir’ in file ‘file.root’ and save them into directory ‘dir’ in file ‘copy.root’:

#include <TFile.h>
#include <TKey.h>

int main(int argc,char**argv)
  TFile*      ifile = new TFile("file.root","READ");
  TDirectory* idir  = (TDirectory*)ifile->Get("dir");

  TFile*      ofile = new TFile("copy.root","RECREATE");
  TDirectory* odir  = (TDirectory*)ofile->mkdir("dir");

  TIter next(idir->GetListOfKeys());
  TKey* key(0);
  while ((key=(TKey*)next())) {
    TObject* obj = key->ReadObj();
  delete odir;
  delete ofile;
  delete ifile;

  return 0;

When I do this on linux slc4 with ROOT 5.18, it works as is; on my Mac using ROOT 5.20 on the other hand, the output directory will be empty unless I add the obj->Write() call. Why? What is the proper way to do it? I thought that if I instantiate an object (e.g. by loading it) and odir is the current directory, the object will be in it, and odir->Write() will capture it?


Hi Philipp,

In v5.18 (and earlier), TObject* obj = key->ReadObj(); was ‘attaching’ some objects (TTrees, TH1, etc.) to the current directory whereas one would expect them to be attached to the directory they are read from (this is especially significant for TTrees).

So in v5.20, we corrected the code so that ReadObj attach the object to the place they are read from. This also mean that your code need to now explicitly call ‘obj->Write’ (or odir->Write(obj); ).

Note that neither your new code nor the old code is copying the TTree correctly. This is because, if the object is a TTree, obj->Write will only copy the TTree meta data and not the user data. For TTree you need to call CloneTree (see TFileMerge, hadd.cxx or tutorials/tree/tree*.C )


Hi Philippe,

thanks for the clarification, I will modify my code accordingly.