<?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>Text Files &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/text-files/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Thu, 02 Apr 2026 16:09:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Build a Simple Find in Files Function</title>
		<link>https://blog.xojo.com/2026/04/02/build-a-simple-find-in-files-function/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Thu, 02 Apr 2026 16:15:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Files]]></category>
		<category><![CDATA[Search]]></category>
		<category><![CDATA[Text Files]]></category>
		<category><![CDATA[Text Processing]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15972</guid>

					<description><![CDATA[Sooner or later most apps need some version of the ability to find text in those files, whether you&#8217;re scanning log files, config files, exported&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Sooner or later most apps need some version of the ability to find text in those files, whether you&#8217;re scanning log files, config files, exported data, or source code.</p>



<p>In this post, we&#8217;ll build a simple Find in Files utility in Xojo that:</p>



<ul class="wp-block-list">
<li>searches the files in a folder</li>



<li>reads each file line by line</li>



<li>performs a plain-text, case-insensitive match</li>



<li>returns the file path, line number, and matching line</li>
</ul>



<p>The goal is simple: build something useful while leaving the door open for the fancier stuff.</p>



<h2 class="wp-block-heading" id="what-this-find-in-files-function-will-do">What this Find in Files function will do</h2>



<p>Let&#8217;s keep the scope clear:</p>



<ul class="wp-block-list">
<li>search one folder</li>



<li>search plain text only</li>



<li>skip subfolders for now</li>



<li>return the matching file path, line number, and line contents</li>
</ul>



<h2 class="wp-block-heading" id="step-1-put-the-result-class-in-the-module">Step 1: A class in a module and some properties</h2>



<p>Before touching the file system, let&#8217;s define what a match looks like.</p>



<p>You could return raw strings, but that gets messy fast. A small class keeps the code readable and gives us an obvious place to extend later. In this version, I like keeping that class inside the same module as the search function. It keeps the entire utility self-contained instead of spraying helper types all over the project.</p>



<p>So, we start by adding a module&nbsp;<code>SearchUtils</code>&nbsp;and inside the module we will add a class&nbsp;<code>SearchHit</code>.</p>



<pre class="wp-block-code"><code>Module SearchUtils

  Class SearchHit

    Public Property FilePath As String
    Public Property LineNumber As Integer
    Public Property LineText As String

    Public Sub Constructor(filePath As String, lineNumber As Integer, lineText As String)
      Self.FilePath = filePath
      Self.LineNumber = lineNumber
      Self.LineText = lineText
    End Sub

  End Class

End Module</code></pre>



<p>Each result stores three things:</p>



<ol class="wp-block-list">
<li>the file path</li>



<li>the line number</li>



<li>the matching line</li>
</ol>



<h2 class="wp-block-heading" id="step-2-walk-through-the-folder">Step 2: Walk through the folder</h2>



<p><code>FolderItem.Children</code> lets us loop through a folder with a <code>For Each</code> loop, which keeps the code clear.</p>



<p>We&#8217;ll also reject bad input early:</p>



<ul class="wp-block-list">
<li>the folder is&nbsp;<code>Nil</code></li>



<li>the folder does not exist</li>



<li>the item passed is not actually a folder</li>



<li>the search term is empty</li>
</ul>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="409" src="https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2-1024x409.png" alt="" class="wp-image-16027" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2-1024x409.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2-300x120.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2-768x307.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2.png 1536w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>This process is simple, fast and effective.</p>



<h2 class="wp-block-heading" id="step-3-read-files-line-by-line">Step 3: Read files line by line</h2>



<p>For text files,&nbsp;<code>TextInputStream.Open</code>&nbsp;is the right tool. From there, we can call&nbsp;<code>ReadLine</code>&nbsp;until&nbsp;<code>EndOfFile</code>&nbsp;becomes&nbsp;<code>True</code>.</p>



<p>I prefer this over&nbsp;<code>ReadAll</code>&nbsp;for a utility like this.&nbsp;<code>ReadAll</code>&nbsp;is fine when the file is small and you know what you&#8217;re doing, but line-by-line reading is a better default here. It keeps memory use in check and gives us line numbers for free.</p>



<p>For the sample code, I&#8217;m explicitly using UTF-8:</p>



<pre class="wp-block-code"><code>input.Encoding = Encodings.UTF8</code></pre>



<p>That keeps the sample predictable. It does&nbsp;<strong>not</strong>&nbsp;mean this code can gracefully decode every text file you throw at it. Files with unknown encodings or binary-ish content are a separate problem, and they deserve their own solution.</p>



<h2 class="wp-block-heading" id="step-4-match-the-text">Step 4: Match the text</h2>



<p>For a plain-text search,&nbsp;<code>String.Contains</code>&nbsp;does exactly what we need:</p>



<pre class="wp-block-code"><code>line.Contains(searchTerm, ComparisonOptions.CaseInsensitive)</code></pre>



<p>It handles the case-insensitivity without the overhead, or the headache, of regex.</p>



<h2 class="wp-block-heading" id="step-5-the-full-module">Step 5: The full module and class and function</h2>



<pre class="wp-block-code"><code>Module SearchUtils

  Public Class SearchHit
    Public Property FilePath As String
    Public Property LineNumber As Integer
    Public Property LineText As String

    Public Sub Constructor(filePath As String, lineNumber As Integer, lineText As String)
      Self.FilePath = filePath
      Self.LineNumber = lineNumber
      Self.LineText = lineText
    End Sub
  End Class

  Public Function FindInFiles(targetFolder As FolderItem, searchTerm As String) As SearchHit()
    Var hits() As SearchHit

    If targetFolder Is Nil Then
      Return hits
    End If

    If Not targetFolder.Exists Or Not targetFolder.IsFolder Then
      Return hits
    End If

    If searchTerm.IsEmpty Then
      Return hits
    End If

    For Each item As FolderItem In targetFolder.Children
      If item Is Nil Then Continue
      If item.IsFolder Then Continue
      If Not item.Exists Then Continue
      If Not item.IsReadable Then Continue

      Try
        Var input As TextInputStream = TextInputStream.Open(item)
        input.Encoding = Encodings.UTF8

        Var lineNumber As Integer = 0

        While Not input.EndOfFile
          Var line As String = input.ReadLine
          lineNumber = lineNumber + 1

          If line.Contains(searchTerm, ComparisonOptions.CaseInsensitive) Then
            hits.Add(New SearchHit(item.NativePath, lineNumber, line))
          End If
        Wend

        input.Close

      Catch error As IOException
        ' Skip files that cannot be read as text.
        Continue
      End Try
    Next

    Return hits
  End Function

End Module</code></pre>



<h2 class="wp-block-heading" id="how-it-works">How it works</h2>



<p>Let&#8217;s break down the important parts.</p>



<h3 class="wp-block-heading" id="input-validation">Input validation</h3>



<p>This block prevents pointless work and avoids avoidable runtime problems:</p>



<pre class="wp-block-code"><code>If targetFolder Is Nil Then
  Return hits
End If

If Not targetFolder.Exists Or Not targetFolder.IsFolder Then
  Return hits
End If

If searchTerm.IsEmpty Then
  Return hits
End If</code></pre>



<p>Rule of thumb: reject bad input early.</p>



<h3 class="wp-block-heading" id="folder-iteration">Folder iteration</h3>



<p>This is the core loop:</p>



<pre class="wp-block-code"><code>For Each item As FolderItem In targetFolder.Children</code></pre>



<p>We&#8217;re only scanning the folder&#8217;s immediate contents. If an item is another folder, we skip it.</p>



<pre class="wp-block-code"><code>If item.IsFolder Then Continue</code></pre>



<h3 class="wp-block-heading" id="safe-text-reading">Safe text reading</h3>



<p>Each file is opened with&nbsp;<code>TextInputStream.Open</code>&nbsp;inside a&nbsp;<code>Try...Catch</code>&nbsp;block:</p>



<pre class="wp-block-code"><code>Try
  Var input As TextInputStream = TextInputStream.Open(item)
  input.Encoding = Encodings.UTF8
  ...
Catch error As IOException
  Continue
End Try</code></pre>



<p>That way, one unreadable file does not take down the whole search. It gets skipped and the rest of the folder still gets processed.</p>



<h3 class="wp-block-heading" id="line-by-line-matching">Line-by-line matching</h3>



<p>This is where the actual work happens:</p>



<pre class="wp-block-code"><code>While Not input.EndOfFile
  Var line As String = input.ReadLine
  lineNumber = lineNumber + 1

  If line.Contains(searchTerm, ComparisonOptions.CaseInsensitive) Then
    hits.Add(New SearchHit(item.NativePath, lineNumber, line))
  End If
Wend</code></pre>



<p>Because we&#8217;re reading one line at a time, attaching the correct line number is trivial.</p>



<h3 class="wp-block-heading" id="why-keep-searchhit-inside-the-module">Why keep&nbsp;<code>SearchHit</code>&nbsp;inside the module?</h3>



<p>Because it belongs to this utility. The search function and its result type are part of the same little unit of behavior, so keeping them together makes the project easier to scan and easier to transform it to a&nbsp;<a href="https://documentation.xojo.com/topics/code_management/sharing_code_among_multiple_projects.html" target="_blank" rel="noreferrer noopener">Library</a>.</p>



<p>It also means code outside the module uses the namespaced type:</p>



<pre class="wp-block-code"><code>Var results() As SearchUtils.SearchHit = SearchUtils.FindInFiles(folder, "xojo")</code></pre>



<h2 class="wp-block-heading" id="using-the-function">Using the function</h2>



<p>Here&#8217;s a simple example that lets the user choose a folder and then writes the results to the debug log:</p>



<pre class="wp-block-code"><code>Var folder As FolderItem = FolderItem.ShowSelectFolderDialog
If folder Is Nil Then Return

Var results() As SearchUtils.SearchHit = SearchUtils.FindInFiles(folder, "error")

For Each hit As SearchUtils.SearchHit In results
  System.DebugLog(hit.FilePath + " | line " + hit.LineNumber.ToString + " | " + hit.LineText)
Next</code></pre>



<p>If you want to display the results in a&nbsp;<code>DesktopListBox</code>, that works nicely too:</p>



<pre class="wp-block-code"><code>Var folder As FolderItem = FolderItem.ShowSelectFolderDialog
If folder Is Nil Then Return

Var results() As SearchUtils.SearchHit = FindInFiles(folder, "error")

ListBox1.RemoveAllRows
ListBox1.ColumnCount = 3

For Each hit As SearchUtils.SearchHit In results
  ListBox1.AddRow(hit.FilePath)
  ListBox1.CellTextAt(ListBox1.LastAddedRowIndex, 1) = hit.LineNumber.ToString
  ListBox1.CellTextAt(ListBox1.LastAddedRowIndex, 2) = hit.LineText
Next</code></pre>



<p>A few sample results might look like this:</p>



<pre class="wp-block-code"><code>C:\Logs\app.log | line 18 | Error connecting to database
C:\Logs\app.log | line 42 | Error writing audit record
C:\Configs\service.txt | line 7 | Last error message: timeout</code></pre>



<h2 class="wp-block-heading" id="practical-limitations-of-this-version">Practical limitations of this version</h2>



<p>This utility is useful, but limited.</p>



<h3 class="wp-block-heading" id="it-assumes-utf-8">It assumes UTF-8</h3>



<p>That is fine for plenty of modern text files, but not all of them. If you&#8217;re dealing with mixed encodings, you&#8217;ll need a smarter approach that detects the file encoding.</p>



<h3 class="wp-block-heading" id="it-doesnt-recurse-into-subfolders">It doesn&#8217;t recurse into subfolders</h3>



<p>That is deliberate. Recursive search is useful, but it adds another layer of behavior and another place to make the code harder to read.</p>



<h2 class="wp-block-heading" id="final-thoughts">Final thoughts</h2>



<p>A basic Find in Files function is one of those utilities that looks small but pays off quickly. This is a base-layer utility. Once you have this working, adding recursion or regex is a much smaller lift.</p>



<p>Let&#8217;s discuss in the&nbsp;<a href="https://forum.xojo.com/">forums</a>.</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Advanced File Processing Techniques: Using Chunks for Handling Large Files</title>
		<link>https://blog.xojo.com/2024/06/10/advanced-file-processing-techniques-using-chunks-for-handling-large-files/</link>
					<comments>https://blog.xojo.com/2024/06/10/advanced-file-processing-techniques-using-chunks-for-handling-large-files/#comments</comments>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Mon, 10 Jun 2024 16:00:00 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Text Files]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13054</guid>

					<description><![CDATA[A recent blog post, A Beginner’s Guide to Handling Text Files in Xojo, covered the basics of text file handling in Xojo. This post delves into advanced techniques for reading and writing large files in chunks. This method is crucial for managing large datasets efficiently, minimizing memory usage, and maintaining application performance.]]></description>
										<content:encoded><![CDATA[
<p>A recent blog post, <a href="https://blog.xojo.com/2024/05/29/a-beginners-guide-to-handling-text-files-in-xojo/">A Beginner’s Guide to Handling Text Files in Xojo</a>, covered the basics of text file handling in Xojo. This post delves into advanced techniques for reading and writing large files in chunks. This method is crucial for managing large datasets efficiently, minimizing memory usage, and maintaining application performance.</p>



<h2 class="wp-block-heading">Why Read and Write in Chunks?</h2>



<p>Loading or writing a large file in one go can overwhelm your application’s memory and degrade performance. Processing files in smaller, manageable chunks allows for better memory management and more responsive applications.</p>



<h2 class="wp-block-heading">Reading Files in Chunks</h2>



<p>To read a large file in chunks, you can repeatedly read smaller portions of the file until you reach the end. Here’s an example:</p>



<pre id="xojo" class="wp-block-code"><code>Var file As FolderItem = FolderItem.ShowOpenFileDialog("text/plain")
If file &lt;> Nil Then
  Const kChunkSize As Integer = 1024  ' 1 KB chunks

  Var inputStream As TextInputStream = TextInputStream.Open(file)
  Var buffer As String

  While Not inputStream.EndOfFile
    buffer = inputStream.Read(kChunkSize)
    // Process the buffer (for demonstration, we'll just print it)
    System.DebugLog(buffer)
 Wend

  inputStream.Close
Else
  MessageBox("No file selected.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>A TextInputStream is created to read the file.</li>



<li>The kChunkSize defines how much data is read at a time.</li>



<li>The file is read in a loop until the end is reached, processing each chunk.</li>
</ul>



<h2 class="wp-block-heading">Writing Files in Chunks</h2>



<p>Writing large files in chunks involves writing smaller portions incrementally. Here’s an example using String.Bytes and String.MiddleBytes for better performance:</p>



<pre id="xojo" class="wp-block-code"><code>Var file As FolderItem = FolderItem.ShowSaveFileDialog("text/plain", "example.txt")
If file &lt;> Nil Then
  Const kChunkSize As Integer = 1024  ' 1 KB chunks

  Var outputStream As TextOutputStream = TextOutputStream.Create(file)
  Var data As String = "Large data string here..." // Your data source
  Var totalBytes As Integer = data.Bytes

  For i As Integer = 0 To totalBytes Step kChunkSize
    Var chunk As String = data.MiddleBytes(i, kChunkSize)
    outputStream.Write(chunk)
  Next

  // Write any remaining data
  If totalBytes Mod kChunkSize &lt;> 0 Then
    Var remainingBytes As Integer = totalBytes Mod kChunkSize
    Var chunk As String = data.MiddleBytes(totalBytes - remainingBytes, remainingBytes)
    outputStream.Write(chunk)
  End If

  outputStream.Close
  MessageBox("File written successfully.")
Else
  MessageBox("No file specified.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>A TextOutputStream is created to write to a file.</li>



<li>The total bytes of the string are calculated for iteration.</li>



<li>Data is written in chunks defined by kChunkSize using String.MiddleBytes for improved performance.</li>



<li>After the loop, any remaining data that didn’t fit into a full chunk is written.</li>
</ul>



<h3 class="wp-block-heading">Practical Example: Processing Large Log Files</h3>



<p>Processing large log files line by line in chunks can be done as follows:</p>



<pre id="xojo" class="wp-block-code"><code>Var file As FolderItem = FolderItem.ShowOpenFileDialog("text/plain")
If file &lt;> Nil Then
  Const kChunkSize As Integer = 4096 ' 4 KB chunks
  Var inputStream As TextInputStream = TextInputStream.Open(file)
  Var buffer, remaining As String
  While Not inputStream.EndOfFile
    buffer = inputStream.Read(kChunkSize)
    buffer = remaining + buffer
    Var lines() As String = buffer.ToArray(EndOfLine)
    // Process all but the last line
    For i As Integer = lines.FirstIndex To lines.LastIndex - 1
      System.DebugLog(lines(i))
    Next
    // Save the last line for the next chunk
    remaining = lines(lines.LastIndex)
  Wend
  // Process any remaining content
  If Not remaining.IsEmpty Then
    System.DebugLog(remaining)
  End If
  inputStream.Close
Else
  MessageBox("No file selected.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>The file is read in larger chunks (4 KB).</li>



<li>The buffer is split into lines, and all but the last line are processed.</li>



<li>The last line is saved and appended to the next chunk to ensure no data is lost.</li>
</ul>



<h3 class="wp-block-heading">Advanced Techniques: Handling Binary Files</h3>



<p>Reading and writing binary files also benefits from chunk processing. Here’s a basic example of reading binary files in chunks:</p>



<pre id="xojo" class="wp-block-code"><code>Var file As FolderItem = FolderItem.ShowOpenFileDialog("")
If file &lt;> Nil Then
  Const kChunkSize As Integer = 1024 ' 1 KB chunks
  Var binaryStream As BinaryStream = BinaryStream.Open(file, False)
  Var buffer As MemoryBlock
  While Not binaryStream.EndOfFile
    buffer = binaryStream.Read(kChunkSize)
    // Process the buffer (for demonstration, we'll just print its size)
    System.DebugLog(buffer.Size.ToString)
  Wend
  binaryStream.Close
Else
  MessageBox("No file selected.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>A BinaryStream is created to read the file.</li>



<li>Data is read in chunks and processed accordingly. </li>
</ul>



<h3 class="wp-block-heading">Writing Binary Files in Chunks</h3>



<p>You can also write binary files in chunks. Here’s a basic example:</p>



<pre id="xojo" class="wp-block-code"><code>Var file As FolderItem = FolderItem.ShowSaveFileDialog("text/plain", "example.txt")
If file &lt;> Nil Then
  Var binaryStream As BinaryStream = BinaryStream.Create(file, True)
  Const kChunkSize As Integer = 1024 ' 1 KB chunks
  Var data As MemoryBlock = ...  ' Your binary data source
  Var totalBytes As Integer = data.Size
  For i As Integer = 0 To totalBytes Step kChunkSize
    Var chunk As MemoryBlock = data.MidB(i, kChunkSize)
    binaryStream.Write(chunk)
  Next
  // Write any remaining data
  If totalBytes Mod kChunkSize &lt;> 0 Then
    Var remainingBytes As Integer = totalBytes Mod kChunkSize
    Var chunk As MemoryBlock = data.MidB(totalBytes - remainingBytes, remainingBytes)
    binaryStream.Write(chunk)
  End If
  binaryStream.Close
  MessageBox("Binary file written successfully.")
Else
  MessageBox("No file specified.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>A BinaryStream is created to write to a file.</li>



<li>Data is written in chunks using MemoryBlock.MidB to handle binary data.</li>



<li>After the loop, any remaining data that didn’t fit into a full chunk is written. </li>
</ul>



<h3 class="wp-block-heading">Using Threads for Large File Operations </h3>



<p>When working with large files, consider using a Thread to perform read and write operations. This keeps the user interface responsive while the file operations are running in the background. </p>



<p>Example of reading a large file in a thread: </p>



<pre id="xojo" class="wp-block-code"><code>Class FileReadThread Inherits Thread
  Private mFile As FolderItem
  Sub Constructor(file As FolderItem)
    mFile = file
  End Sub
  Sub Run()
    Const kChunkSize As Integer = 1024 ' 1 KB chunks
    Var inputStream As TextInputStream = TextInputStream.Open(mFile)
    Var buffer As String
    While Not inputStream.EndOfFile
      buffer = inputStream.Read(kChunkSize)
      // Process the buffer (for demonstration, we'll just print it)
      System.DebugLog(buffer)
    Wend
    inputStream.Close
  End Sub
End Class

// Usage
Var file As FolderItem = FolderItem.ShowOpenFileDialog("text/plain")
If file &lt;> Nil Then
  Var fileThread As New FileReadThread(file)
  fileThread.Run
Else
  MessageBox("No file selected.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>A Thread subclass is created to handle file reading.</li>



<li>The main UI remains responsive while the thread processes the file in the background. </li>
</ul>



<h2 class="wp-block-heading">Conclusion</h2>



<p>Handling large files efficiently is crucial for developing robust Xojo applications. By reading and writing files in chunks, you can manage memory usage better and ensure your application remains responsive even when dealing with large datasets. Experiment with these techniques in your projects to experience the benefits. </p>



<p>Happy coding!</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.xojo.com/2024/06/10/advanced-file-processing-techniques-using-chunks-for-handling-large-files/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>A Beginner&#8217;s Guide to Handling Text Files in Xojo</title>
		<link>https://blog.xojo.com/2024/05/29/a-beginners-guide-to-handling-text-files-in-xojo/</link>
					<comments>https://blog.xojo.com/2024/05/29/a-beginners-guide-to-handling-text-files-in-xojo/#comments</comments>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Wed, 29 May 2024 15:33:40 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Text Files]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12946</guid>

					<description><![CDATA[As developers, we often need to work with text files. This could be for reading configuration settings, parsing log files, or generating reports. Text files are a common part of software development, and knowing how to access and manipulate them is important for building strong and flexible Xojo applications. In this article, we will make use the key Xojo classes and techniques for working with text files. We will start by looking at how to read the contents of text files using the TextInputStream class. You will learn how to read an entire file into a string and how to process the file line-by-line.]]></description>
										<content:encoded><![CDATA[
<p>As developers, we often need to work with text files. This could be for reading configuration settings, parsing log files, or generating reports. Text files are a common part of software development, and knowing how to access and manipulate them is important for building strong and flexible Xojo applications.</p>



<p>In this article, we will make use of the key Xojo classes and techniques for working with text files. We will start by looking at how to read the contents of text files using the <a href="https://docs.xojo.com/api/files/textinputstream.html" data-type="link" data-id="https://docs.xojo.com/api/files/textinputstream.html" target="_blank" rel="noreferrer noopener">TextInputStream</a> class. You will learn how to read an entire file into a string and how to process the file line-by-line.</p>



<p>Next, we will cover writing to text files using the <a href="https://docs.xojo.com/api/files/textoutputstream.html" data-type="link" data-id="https://docs.xojo.com/api/files/textoutputstream.html" target="_blank" rel="noreferrer noopener">TextOutputStream</a> class. You will see examples of how to write a complete string to a file and how to write individual lines one-by-one, useful when logging information or saving user preferences.</p>



<p>By the end of this post, you will understand the core techniques for accessing, reading, and writing text files in your Xojo applications. These skills will help you build more robust and flexible software that can work with a wide range of data sources and formats.</p>



<h2 class="wp-block-heading">Reading Text Files</h2>



<p>When it comes to reading the contents of text files in Xojo, the TextInputStream class is the primary tool you&#8217;ll use. This class provides methods for both reading the entire file at once, as well as reading it line-by-line.</p>



<h3 class="wp-block-heading">Using TextInputStream to Open and Read Text Files</h3>



<p>Here is an example that demonstrates how to read an entire file into a string:</p>



<pre id="xojo" class="wp-block-code"><code>// Step 1: Open the File
Var file As FolderItem
file = FolderItem.ShowOpenFileDialog("text/plain") // Show an open file dialog to select the file

If file &lt;&gt; Nil Then
  // Step 2: Create a TextInputStream
  Var inputStream As TextInputStream
  inputStream = TextInputStream.Open(file)
  
  // Step 3: Read the File
  Var fileContents As String
  fileContents = inputStream.ReadAll
  
  // Step 4: Close the Stream
  inputStream.Close
  
  // Output the file contents (for demonstration purposes)
  MessageBox(fileContents)
Else
  MessageBox("No file selected.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>The <a href="https://documentation.xojo.com/api/files/folderitem.html#folderitem-showopenfiledialog" data-type="link" data-id="https://documentation.xojo.com/api/files/folderitem.html#folderitem-showopenfiledialog" target="_blank" rel="noreferrer noopener">FolderItem.ShowOpenFileDialog</a> method is used to display a file dialog, allowing the user to select a text file.</li>



<li>The <a href="https://documentation.xojo.com/api/files/textinputstream.html#textinputstream-open" data-type="link" data-id="https://documentation.xojo.com/api/files/textinputstream.html#textinputstream-open" target="_blank" rel="noreferrer noopener">TextInputStream.Open</a> method opens the selected file for reading.</li>



<li>The <a href="https://documentation.xojo.com/api/files/textinputstream.html#textinputstream-readall" data-type="link" data-id="https://documentation.xojo.com/api/files/textinputstream.html#textinputstream-readall" target="_blank" rel="noreferrer noopener">ReadAll</a> method reads the entire contents of the file into the fileContents string.</li>



<li>The Close method closes the TextInputStream.</li>
</ul>



<p>This approach is useful when you need to process the entire contents of a text file at once. However, for larger files, you may want to read the file line-by-line to manage memory usage more efficiently, which we will cover in the next section.</p>



<h3 class="wp-block-heading">Using TextInputStream to Read Line-by-Line</h3>



<p>Reading a file line-by-line is often more efficient, especially for large files. This method allows you to process each line individually, reducing memory usage and enabling you to handle large datasets more effectively.</p>



<p>Here is an example that demonstrates how to read a file line-by-line in Xojo:</p>



<pre id="xojo" class="wp-block-code"><code>// Step 1: Open the File
Var file As FolderItem
file = FolderItem.ShowOpenFileDialog("text/plain") // Show an open file dialog to select the file

If file &lt;&gt; Nil Then
  // Step 2: Create a TextInputStream
  Var inputStream As TextInputStream
  inputStream = TextInputStream.Open(file)
  
  // Step 3: Read Each Line
  Var line As String
  While Not inputStream.EndOfFile
    line = inputStream.ReadLine
    // Process each line (for demonstration purposes, we'll just output each line in a MessageBox)
    MessageBox(line)
  Wend
  
  // Step 4: Close the Stream
  inputStream.Close
Else
  MessageBox("No file selected.")
End If</code></pre>



<p>This approach is particularly useful when you need to process or analyze each line of a text file individually, such as when parsing log files or reading configuration settings.</p>



<h2 class="wp-block-heading">Writing Text Files</h2>



<p>Writing text files in Xojo is just as straightforward as reading them. The <a href="https://documentation.xojo.com/api/files/textoutputstream.html" data-type="link" data-id="https://documentation.xojo.com/api/files/textoutputstream.html" target="_blank" rel="noreferrer noopener">TextOutputStream</a> class allows you to write data to text files, either all at once or line-by-line and it&#8217;s quite easy.</p>



<h3 class="wp-block-heading">Using TextOutputStream to Write Entire Files</h3>



<p>To write an entire string to a file, follow these steps:</p>



<pre id="xojo" class="wp-block-code"><code>// Step 1: Allow the user to set the path and name of the text file we are about to create
Var file As FolderItem
file = FolderItem.ShowSaveFileDialog("text/plain", "example.txt") // Show a save file dialog to specify the file

If file &lt;&gt; Nil Then
  // Step 2: Create a TextOutputStream
  Var outputStream As TextOutputStream
  outputStream = TextOutputStream.Create(file)
  
  // Step 3: Write to the File
  Var fileContents As String = "Hello, Xojo!"
  outputStream.Write(fileContents)
  
  // Step 4: Close the Stream
  outputStream.Close
  
  MessageBox("File written successfully.")
Else
  MessageBox("No file specified.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>The <a href="https://documentation.xojo.com/api/files/folderitem.html#folderitem-showsavefiledialog" data-type="link" data-id="https://documentation.xojo.com/api/files/folderitem.html#folderitem-showsavefiledialog" target="_blank" rel="noreferrer noopener">FolderItem.ShowSaveFileDialog</a> method is used to display a save file dialog, allowing the user to specify the file name and location.</li>



<li>The <a href="https://documentation.xojo.com/api/files/textoutputstream.html#textoutputstream-create" target="_blank" rel="noreferrer noopener">TextOutputStream.Create</a> method creates a new file or overwrites an existing file.</li>



<li>The <a href="https://documentation.xojo.com/api/files/textoutputstream.html#textoutputstream-write" target="_blank" rel="noreferrer noopener">Write</a> method writes the fileContents string to the file.</li>



<li>The Close method closes the TextOutputStream.</li>
</ul>



<h3 class="wp-block-heading">Using TextOutputStream to Write Line-by-Line</h3>



<p>Writing a file line-by-line is useful when you need to write data incrementally or when dealing with large datasets.</p>



<p>To write a file line-by-line, follow these steps:</p>



<pre id="xojo" class="wp-block-code"><code>// Step 1: Allow the user to set the path and name of the text file we are about to create
Var file As FolderItem
file = FolderItem.ShowSaveFileDialog("text/plain", "example.txt") // Show a save file dialog to specify the file

If file &lt;&gt; Nil Then
  // Step 2: Create a TextOutputStream
  Var outputStream As TextOutputStream
  outputStream = TextOutputStream.Create(file)
  
  // Step 3: Write Each Line
  Var lines() As String = Array("Line 1", "Line 2", "Line 3")
  For Each line As String In lines
    outputStream.WriteLine(line)
  Next
  
  // Step 4: Close the Stream
  outputStream.Close
  
  MessageBox("File written successfully.")
Else
  MessageBox("No file specified.")
End If</code></pre>



<p>In this example:</p>



<ul class="wp-block-list">
<li>The FolderItem.ShowSaveFileDialog method is used to display a save file dialog, allowing the user to specify the file.</li>



<li>The TextOutputStream.Create method creates a new file or overwrites an existing file.</li>



<li>The <a href="https://documentation.xojo.com/api/files/textoutputstream.html#textoutputstream-writeline" data-type="link" data-id="https://documentation.xojo.com/api/files/textoutputstream.html#textoutputstream-writeline" target="_blank" rel="noreferrer noopener">WriteLine</a> method writes each line from the lines array to the file.</li>



<li>The Close method closes the TextOutputStream.</li>
</ul>



<p>By understanding these methods, you can choose the one that best fits your needs. Writing the entire file at once is useful for smaller datasets or when you need to write all data simultaneously. Writing line-by-line is more efficient for larger datasets or when you need to write data incrementally.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>This article has provided you with the skills to handle text files in Xojo using the <a href="https://documentation.xojo.com/api/files/textinputstream.html" target="_blank" rel="noreferrer noopener">TextInputStream</a> and <a href="https://documentation.xojo.com/api/files/textoutputstream.html" target="_blank" rel="noreferrer noopener">TextOutputStream</a> classes. We covered the following essential techniques:</p>



<p><strong>Reading Text Files:</strong></p>



<ul class="wp-block-list">
<li>Reading entire files into a string using TextInputStream.ReadAll</li>



<li>Reading files line-by-line using TextInputStream.ReadLine</li>
</ul>



<p><strong>Writing Text Files:</strong></p>



<ul class="wp-block-list">
<li>Writing entire strings to a file using TextOutputStream.Write</li>



<li>Writing lines to a file using TextOutputStream.WriteLine</li>
</ul>



<p>Try applying these techniques in your own projects. Experiment with different methods to see how they can help you manage text files more effectively. The <a href="https://docs.xojo.com/topics/file_management/accessing_text_files.html" target="_blank" rel="noreferrer noopener">official Xojo documentation on working with text files</a> is a great resource for further reading.</p>



<p>Ready to get started? <a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo for free</a> and begin building your applications today!</p>



<p>Happy coding!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.xojo.com/2024/05/29/a-beginners-guide-to-handling-text-files-in-xojo/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
