<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Culverson Software-Custom DAQ Software labVIEW &#187; Files</title>
	<atom:link href="http://culverson.com/category/files/feed/" rel="self" type="application/rss+xml" />
	<link>http://culverson.com</link>
	<description>Custom Labview Data Acquisition Software Maine</description>
	<lastBuildDate>Sat, 05 Mar 2011 21:12:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Where Am I?</title>
		<link>http://culverson.com/where-am-i/</link>
		<comments>http://culverson.com/where-am-i/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 15:51:12 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Files]]></category>
		<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[User Interface]]></category>

		<guid isPermaLink="false">http://jimdugan.com/culverson/?p=77</guid>
		<description><![CDATA[Use a tool to find yourself. When your program is large enough to have multiple folders to store files in, or read them from, then you have to know, or find, where those folders are. Asking your users to create those folders will surely raise the ire of some, if not most of them. After [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><strong><em>Use a tool to find yourself.</em></strong></p>
<p>When your program is large enough to have multiple folders to store files in, or read them from, then you have to know, or find, where those folders are.</p>
<p>Asking your users to create those folders will surely raise the ire of some, if not most of them. After all, the computer is capable of creating folders, the computer knows what folders are needed, why is this %!^#$^ box asking ME to do its job?</p>
<p>Complaining to the user about a folder not being found is in the same league; no matter how many times you print it in the instructions that they have to create the folders beforehand, folks will run your program and object to the complaint it gives them.</p>
<p>So, you put in things like CREATE FOLDER (”C:\MyWonderfulProgram\ConfigFiles”), and everything is all groovy, right?</p>
<p>Not exactly. Maybe I want to put this program on drive D:. Maybe I want to run it under OS X. Maybe I want to put it under C:\2009\March\Mediocre Programs. What do you do then?</p>
<p>One solution is to make all these folders relative to the root. And to do that, you have to find out where you are.</p>
<h3>Download a Helper</h3>
<p>I have used the following VI, for that purpose, since 1992.</p>
<p><a href="http://culverson.com/site09/wp-content/uploads/2009/09/RootFolder.vi.zip">Click to download Root Folder.vi</a></p>
<p>Basically, put it into a library (LLB). Call it early on when your main VI starts.<br />
Call it with INIT = TRUE, once. When you INIT it, you can either pass the path of the calling VI (This VI’s Path) in the FILE palette, or leave the path input unwired. If you leave it unwired, it assumes that it’s in a library, and finds the path to the folder containing the library. If you provide a path, it assumes the path is to a VI in a library, and provides the path to the folder containing that library.<br />
For our purposes, a library and an executable are the same thing, and this code works unmodified in either situation. Do not use it if it is not in a library.<br />
After INITing it once, you can call it wherever you want to find out the root folder. You can then use BUILD PATH and create or open folders using the root folder and have them work anywhere.</p>
<p><strong>Caution:</strong> Some operating systems (VISTA, in particular) will write-protect the APPLICATIONS directory, so that if the program tries to create a file or folder in that directory, it will be prevented from doings so, unless the app is run as an administrator. If you must run in that situation, consider a different method of locating the files you want to create / use.</p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/where-am-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hybrid Data Files</title>
		<link>http://culverson.com/hybrid-data-files/</link>
		<comments>http://culverson.com/hybrid-data-files/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 15:55:27 +0000</pubDate>
		<dc:creator>Jim</dc:creator>
				<category><![CDATA[Data Handling]]></category>
		<category><![CDATA[Files]]></category>
		<category><![CDATA[LabVIEW]]></category>

		<guid isPermaLink="false">http://jimdugan.com/culverson/?p=81</guid>
		<description><![CDATA[Combine BINARY and DATALOG files for the best of both worlds. In LabVIEW, there are three kinds of files: TEXT files. Ordinary text, stored in human-readable form, with spaces and line feeds, etc. BINARY files. Raw information stored as machine-readable information. A 32-bit integer is stored in 4 bytes. A double-precision number is stored in [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><em><strong>Combine BINARY and DATALOG files for the best of both worlds.</strong></em></p>
<p>In LabVIEW, there are three kinds of files:</p>
<ul>
<li>TEXT files. Ordinary text, stored in human-readable form, with spaces and line feeds, etc.</li>
<li>BINARY files. Raw information stored as machine-readable information. A 32-bit integer is stored in 4 bytes. A double-precision number is stored in 8 bytes.</li>
<li>DATALOG files. Structured data, suitable for quick transfer between a memory structure and the disk file.</li>
</ul>
<p>I have long used Datalog files for configuration data.  They offer several advantages:</p>
<ul>
<li>EXTREMELY simple reading/writing. No matter how complicated the data structure, you just open the file, write the structure to it, and close the file. No muss, no fuss. I have a project where the datalog file is a single record of maybe 200 k Bytes. It’s still all done with a single WRITE FILE call.</li>
<li>Being binary, users are reluctant to open it in their text editors and twiddle about. You won’t get a service call to figure out that the user set the serial port to COM1.76 and the alarm level to 0 ( <span><em>But it was working perfectly yesterday!</em></span> ).</li>
<li>Compactness. A DBL is 8 bytes. The value -12.3456 is 8 bytes, not even counting the delimiters separating it from it’s neighbors. If space is truly an issue, use SGL (4 bytes) instead of DBL.</li>
<li>If your panel is set to allow a number to vary between 10 and 20, then that’s what gets stored. You don’t have to check every number in the file to see if it’s in range. Since you wrote it there, it’s correct.</li>
<li>Format checking. Even if you use the standard file dialogs for choosing files (rather than a custom one), you can set it so that it will show only files of the correct type. The user has fewer wrong files to choose from, therefore the odds of a mistake are lessened.</li>
</ul>
<p>There are a couple of disadvantages, though:</p>
<ul>
<li>Rigid formatting. The thing that makes it so easy to read and write, turns around and complicates things when it’s time to revise the format. If you add or remove so much as a single item, or re-arrange the order of things, then the old files are not readable anymore. You can attempt to compensate for this by adding spare fields at the start, but if you make a change to the format, you will have to make an updater which reads the old files and writes new ones in their place, or else all the old files are worthless.</li>
<li>Non-portability. The tamper-resistance feature can be a disadvantage if the file must be available in other (non-LabVIEW) applications. For this reason, datalog format is best suited to files that have limited, well-defined uses.</li>
</ul>
<p>Typically, a data-acquisition program, when used over a reasonable period of time, needs a configuration file to define which channels to use, what their scale factors are, their names, and units, etc., etc. The data recorded in “Run 107″ was recorded using “JOEs setup”, but the data recorded in “Run 108″ was recorded with “JOEs Other Setup”. So how do you keep the files paired? You don’t. You can try various naming schemes, but sooner or later, some mistake will leave the user with a missing or mismatched CONFIG and DATA file pair.</p>
<p>I avoid that whole scenario by including the config data structure inside the data file. Every data file contains the config used to record it. You just put the config cluster inside a large cluster that includes your data, and record that. There is no question about which scale factor was used on the flatistrat channel, because it’s recorded right there. It’s a bit wasteful in terms of disk space, but not terribly so.</p>
<h3>Datalog + Binary = Hybrid</h3>
<p>So, given all that, suppose you have a LOT of data to record. The config data is a small portion, and the data is huge. There’s a problem with the idea of a data file being a cluster containing the config structure and the data. And that problem is memory size. To write a cluster to a datalog file, you have to have the data all in one place. If your data is stored in some other place as it’s acquired, then writing the file means making a COPY of your huge data and putting into the file cluster before writing the file. That’s wasteful. And back in the days when 8 Megabytes was all the RAM a machine could hold, and my clients needed to record more, it wasn’t even POSSIBLE.</p>
<p>To solve those issues, I invented a hybrid file. That term is my own label; it is not an official LabVIEW term. The idea is that you write the config data as a DATALOG file, and close it. Then you open the SAME file as a binary file , skip past the datalog portion, and write binary data. You get the benefit of both worlds: it’s easy to read / write the config header with ordinary datalog operations, and it’s easy to read the binary data with binary operations. You can write the data as you need to; you don’t need to make copies. You can write more data than you have RAM for. You just have to remember that the file doesn’t start at offset zero. It’s perfect, right?</p>
<p>Almost.</p>
<p>You have to figure out where the start of binary data should be, and that’s not trivial. LabVIEW’s DATALOG files include their own header, and the structure and size of that header is not public information. However, you can make some deductions. Since the FILE DIALOG can discriminate between datalog files of different structure, the structure format has to be embedded in the file itself. So what I do is flatten the datalog portion to a string and get it’s size. I take the TYPE STRING (which is not really a string) that comes out of the FLATTEN function, and flatten that and get another size. I add those two sizes together, and round it UP to the next highest multiple of 4096 or so. That works for any size structure, as it includes an estimate for the Datalog header, as well as our own header.</p>
<p>When you read the file, you do the same thing, and compute the offset where the binary data starts.</p>
<p>One more gotcha. Occasionally, National Instruments changes the format used in Datalog files. Usually it’s a minor change, and usually LabVIEW handles it automatically. You may have seen the message “This file was recorded using an older version of LabVIEW, it must be updated to be read. Do you want to update it?”. All that is well and good if it’s a plain Datalog file, but if it’s a hybrid file, LabVIEW doesn’t know anything about the binary data you’ve stuck on the end. So it will open the datalog portion, and re-write a new datalog portion, truncating everything after that, including your data. Beware.</p>
<p>Still this method brings more benefits to the table that it brings problems, so  consider it for your own projects.</p>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/hybrid-data-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
