Click here to Skip to main content
15,896,063 members
Articles / Web Development / IIS

Reading a text file in ASP.

Rate me:
Please Sign up or sign in to vote.
4.96/5 (15 votes)
18 Mar 2009CPOL 764.6K   4.1K   54  
How to read a text file on a server using VBScript in ASP
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Linking this library statically or dynamically with other modules is making
// a combined work based on this library.  Thus, the terms and conditions of
// the GNU General Public License cover the whole combination.
//

#ifndef VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED
#define VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED


#include <algorithm>

#include "../vmime/utility/inputStream.hpp"
#include "../vmime/utility/outputStream.hpp"


namespace vmime {
namespace utility {


/** A stream whose input is filtered.
  */

class VMIME_EXPORT filteredInputStream : public inputStream
{
public:

	virtual size_type getBlockSize();

	/** Return a reference to the stream being filtered.
	  *
	  * @return stream being filtered
	  */
	virtual inputStream& getPreviousInputStream() = 0;
};


/** A stream whose output is filtered.
  */

class VMIME_EXPORT filteredOutputStream : public outputStream
{
public:

	virtual size_type getBlockSize();

	/** Return a reference to the stream being filtered.
	  *
	  * @return destination stream for filtered data
	  */
	virtual outputStream& getNextOutputStream() = 0;
};


/** A filtered input stream which replaces "\n.."
  * sequences with "\n." sequences.
  */

class VMIME_EXPORT dotFilteredInputStream : public filteredInputStream
{
public:

	/** Construct a new filter for the specified input stream.
	  *
	  * @param is stream from which to read data to be filtered
	  */
	dotFilteredInputStream(inputStream& is);

	inputStream& getPreviousInputStream();

	bool eof() const;

	void reset();

	size_type read(value_type* const data, const size_type count);

	size_type skip(const size_type count);

private:

	inputStream& m_stream;

	value_type m_previousChar2; // (N - 1)th character of previous buffer
	value_type m_previousChar1; // (N)th (last) character of previous buffer
};


/** A filtered output stream which replaces "\n."
  * sequences with "\n.." sequences.
  */

class VMIME_EXPORT dotFilteredOutputStream : public filteredOutputStream
{
public:

	/** Construct a new filter for the specified output stream.
	  *
	  * @param os stream into which write filtered data
	  */
	dotFilteredOutputStream(outputStream& os);

	outputStream& getNextOutputStream();

	void write(const value_type* const data, const size_type count);
	void flush();

private:

	outputStream& m_stream;
	value_type m_previousChar;
	bool m_start;
};


/** A filtered output stream which replaces CRLF sequences
  * with single LF characters.
  */

class VMIME_EXPORT CRLFToLFFilteredOutputStream : public filteredOutputStream
{
public:

	/** Construct a new filter for the specified output stream.
	  *
	  * @param os stream into which write filtered data
	  */
	CRLFToLFFilteredOutputStream(outputStream& os);

	outputStream& getNextOutputStream();

	void write(const value_type* const data, const size_type count);
	void flush();

private:

        outputStream& m_stream;
	value_type m_previousChar;
};


/** A filtered output stream which replaces CR or LF characters
  * with CRLF sequences.
  */

class VMIME_EXPORT LFToCRLFFilteredOutputStream : public filteredOutputStream
{
public:

	/** Construct a new filter for the specified output stream.
	  *
	  * @param os stream into which write filtered data
	  */
	LFToCRLFFilteredOutputStream(outputStream& os);

	outputStream& getNextOutputStream();

	void write(const value_type* const data, const size_type count);
	void flush();

private:

	outputStream& m_stream;
	value_type m_previousChar;
};


/** A filtered input stream which stops when a specified sequence
  * is found (eof() method will return 'true').
  */

template <int COUNT>
class VMIME_EXPORT stopSequenceFilteredInputStream : public filteredInputStream
{
public:

	/** Construct a new filter for the specified input stream.
	  *
	  * @param is stream from which to read data to be filtered
	  * @param sequence sequence on which to stop
	  */
	stopSequenceFilteredInputStream(inputStream& is, const value_type* sequence)
		: m_stream(is), m_sequence(sequence), m_found(0), m_eof(false)
	{
	}

	inputStream& getPreviousInputStream()
	{
		return (m_stream);
	}

	bool eof() const
	{
		return (m_found == COUNT || m_eof);
	}

	void reset()
	{
		m_found = 0;
		m_stream.reset();
	}

	size_type read(value_type* const data, const size_type count);

	size_type skip(const size_type /* count */)
	{
		// Not supported
		return 0;
	}

private:

	inputStream& m_stream;

	const value_type* m_sequence;
	size_type m_found;

	bool m_eof;
};


template <>
stream::size_type stopSequenceFilteredInputStream <1>::read
	(value_type* const data, const size_type count);


template <int COUNT>
stream::size_type stopSequenceFilteredInputStream <COUNT>::read
	(value_type* const data, const size_type count)
{
	// Read buffer must be at least 'COUNT' size + 1 byte
	if (eof() || count <= COUNT)
		return 0;

	if (m_stream.eof())
	{
		if (m_found != 0)
		{
			const size_type found = m_found;

			for (size_type f = 0 ; f < found ; ++f)
				data[f] = m_sequence[f];

			m_found = 0;
			m_eof = true;

			return (found);
		}
		else
		{
			m_eof = true;
			return 0;
		}
	}

	size_type read = m_stream.read(data, count - COUNT);

	value_type* end = data + read;
	value_type* pos = data;

	while (pos < end)
	{
		// Very simple case, search for the whole sequence
		if (m_found == 0)
		{
			while (pos < end)
			{
				pos = std::find(pos, end, m_sequence[0]);

				if (pos == end)
					return (read);

				m_found = 1;
				++pos;

				while (pos < end && m_found < COUNT && m_sequence[m_found] == *pos)
				{
					++m_found;
					++pos;
				}

				// Didn't found whole sequence
				if (m_found != COUNT)
				{
					// We reached the end of the buffer
					if (pos == end)
					{
						return (read - m_found);
					}
					// Common prefix but not whole sequence
					else
					{
						m_found = 0;
					}
				}
				// Whole sequence found
				else
				{
					// End of stream
					return (pos - data - m_found);
				}
			}
		}
		// More complex case: search for a sequence which has begun
		// in a previous buffer
		else
		{
			// Search for the end of the previously started sequence
			while (pos < end && m_found < COUNT && m_sequence[m_found] == *pos)
			{
				++m_found;
				++pos;
			}

			if (m_found != COUNT)
			{
				// End of buffer
				if (pos == end)
				{
					// No data: this buffer is a sub-sequence of the
					// searched sequence
					return 0;
				}
				// Common prefix
				else
				{
					// We have to reinject the incomplete sequence into
					// the stream data

					// -- shift right data
					const size_type n = pos - data;

					value_type* newEnd = data + read + m_found - n;
					value_type* oldEnd = data + read;

					for (size_type i = 0 ; i < read - n ; ++i)
					{
						--newEnd;
						--oldEnd;

						*newEnd = *oldEnd;
					}

					// -- copy the prefix just before data
					for (size_type f = 0 ; f < m_found ; ++f)
						data[f] = m_sequence[f];

					read += m_found - n;
					end += m_found - n;

					m_found = 0;
				}
			}
			else
			{
				return 0;  // no more data
			}
		}
	}

	return read;
}


} // utility
} // vmime


#endif // VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder CodeProject
Canada Canada
Chris Maunder is the co-founder of CodeProject and ContentLab.com, and has been a prominent figure in the software development community for nearly 30 years. Hailing from Australia, Chris has a background in Mathematics, Astrophysics, Environmental Engineering and Defence Research. His programming endeavours span everything from FORTRAN on Super Computers, C++/MFC on Windows, through to to high-load .NET web applications and Python AI applications on everything from macOS to a Raspberry Pi. Chris is a full-stack developer who is as comfortable with SQL as he is with CSS.

In the late 1990s, he and his business partner David Cunningham recognized the need for a platform that would facilitate knowledge-sharing among developers, leading to the establishment of CodeProject.com in 1999. Chris's expertise in programming and his passion for fostering a collaborative environment have played a pivotal role in the success of CodeProject.com. Over the years, the website has grown into a vibrant community where programmers worldwide can connect, exchange ideas, and find solutions to coding challenges. Chris is a prolific contributor to the developer community through his articles and tutorials, and his latest passion project, CodeProject.AI.

In addition to his work with CodeProject.com, Chris co-founded ContentLab and DeveloperMedia, two projects focussed on helping companies make their Software Projects a success. Chris's roles included Product Development, Content Creation, Client Satisfaction and Systems Automation.

Comments and Discussions