Reputation: 1259
This may be a simple task but at the moment I really have no clue how I could do this in a simple way. I have the following situation, I have a script written in COFFEE, the scripting language of the 3D program Cinema 4D. Now this script is writing position data in the following format into a text file (rtf in that case but can be a .txt aswell).
0 0.0 471.2 0.0
1 0.0 470.5 0.0
2 0.0 468.8 0.0
3 0.0 465.9 0.0
4 0.0 461.9 0.0
5 0.0 456.8 0.0
6 0.0 450.5 0.0
7 0.0 443.2 0.0
8 0.0 434.8 0.0
9 0.0 425.2 0.0
Frame, X, Y, Z.
Now what I need to do is getting this position data into this format:
Transform Position
Frame X pixels Y pixels Z pixels
0 0.0 471.2 0.0
1 0.0 470.5 0.0
2 0.0 468.8 0.0
End of Keyframe Data
It is not really visible here but there are no spaces in here, everything is spaced with tab (maybe copy that to notepad to really see the tabs). It's important that I have tabs between every number, there can be spaces but I need exactly one tab character everytime. So the most important part is, how do I get those numbers from the first data set and bring and let the program add a \t between every number?
I tried to do this within the script but the script fails if I use a tab instead of several spaces between my positions. I searched quite a lot but couldn't find any good solution for this. I'm familiar with C++ and a little batch script but I'm happy for every solution even if I have to learn the basics of another language.
I tried to find a way in C++ but no way that I came up with could format an n number of lines and every single one was way to complicated. The number of frames/lines varies everytime so I never have a fixed line count.
Upvotes: 1
Views: 1765
Reputation: 77424
An example Python script if interested.
#!c:/Python/python.exe -u
# Or point it at your desired Python path
# Or on Unix something like: !/usr/bin/python
# Function to reformat the data as requested.
def reformat_data(input_file, output_file):
# Define the comment lines you'll write.
header_str = "Transform\tPosition\n"
column_str = "\tFrame\tX pixels\tY pixels\tZ pixels\n"
closer_str = "End of Keyframe Data\n"
# Open the file for reading and close after getting lines.
try:
infile = open(input_file)
except IOError:
print "Invalid input file name..."
exit()
lines = infile.readlines()
infile.close()
# Open the output for writing. Write data then close.
try:
outfile = open(output_file,'w')
except IOError:
print "Invalid output file name..."
exit()
outfile.write(header_str)
outfile.write(column_str)
# Reformat each line to be tab-separated.
for line in lines:
line_data = line.split()
if not (len(line_data) == 4):
# This skips bad data lines, modify behavior if skipping not desired.
pass
else:
outfile.write("\t".join(line_data)+"\n")
outfile.write(closer_str)
outfile.close()
#####
# This below gets executed if you call
# python <name_of_this_script>.py
# from the Powershell/Cygwin/other terminal.
#####
if __name__ == "__main__":
reformat_data("/path/to/input.txt", "/path/to/output.txt")
Upvotes: 1
Reputation: 4924
Something like this might work. I didn't do any special formatting of the numbers, so if you need that you'll need to add it. If you're worried about a malformed input file, like not enough numbers on a line then you'd want to add some additional error checking to guard against it.
#include <fstream>
#include <iostream>
#include <vector>
bool Convert(const char* InputFilename, const char* OutputFilename)
{
std::ifstream InFile(InputFilename);
if(!InFile)
{
std::cout << "Could not open input file '" << InputFilename << "'" << std::endl;
return false;
}
struct PositionData
{
double FrameNum;
double X;
double Y;
double Z;
};
typedef std::vector<PositionData> PositionVec;
PositionVec Positions;
PositionData Pos;
while(InFile)
{
InFile >> Pos.FrameNum >> Pos.X >> Pos.Y >> Pos.Z;
Positions.push_back(Pos);
}
std::ofstream OutFile(OutputFilename);
if(!OutFile)
{
std::cout << "Could not open output file '" << OutputFilename << "'" << std::endl;
return false;
}
OutFile << "Transform\tPosition\n\tFrame\tX pixels\tY pixels\tZ pixels" << std::endl;
for(PositionVec::iterator it = Positions.begin(); it != Positions.end(); ++it)
{
const PositionData& p(*it);
OutFile << "\t" << p.FrameNum << "\t" << p.X << "\t" << p.Y << "\t" << p.Z << std::endl;
}
OutFile << "End of Keyframe Data" << std::endl;
return true;
}
int main(int argc, char* argv[])
{
if(argc < 3)
{
std::cout << "Usage: convert <input filename> <output filename>" << std::endl;
return 0;
}
bool Success = Convert(argv[1], argv[2]);
return Success;
}
Upvotes: 2
Reputation: 49986
yet another example using regexps
#include <fstream>
#include <iostream>
#include <regex>
#include <algorithm>
int main()
{
using namespace std;
ifstream inf("TextFile1.txt");
string data((istreambuf_iterator<char>(inf)), (istreambuf_iterator<char>()));
regex reg("([\\d|\.]+)\\s+([\\d|\.]+)\\s+([\\d|\.]+)\\s+([\\d|\.]+)");
sregex_iterator beg(data.cbegin(), data.cend(), reg), end;
cout << "Transform\tPosition" << endl;
cout << "\tFrame\tX pixels\tY pixels\tZ pixels" << endl;
for_each(beg, end, [](const smatch& m) {
std::cout << "\t" << m.str(1) << "\t" << m.str(2) << "\t" << m.str(3) << "\t" << m.str(4) << std::endl;
});
cout << "End of Keyframe Data" << endl;
}
Upvotes: 2