需求: 需要支持 远程打开 FTP或者网络上的 tif或者img文件, 但是GDAL不能依赖curl编译, 无法直接使用 /vsicurl/ftp://192.168.0.22/a.tif 这种路径丢给GDALOpen去打开tif文件;

解决方案:

GDAL在支持ftp或者网络数据集得时候定义了一套虚拟文件系统接口, 所有打开本地或者远程资源都是用 VSIFilesystemHandler 和 VSIVirtualHandle.这两个接口操作.

经过研究发现只需要实现以上两个接口并注册进GDAL里面他就会自动来根据操作打开文件,然后去读取文件内容.

需要自行实现一个 VSIFilesystemHandler 和 VSIVirtualHandle.

其中VSIFilesystemHandler需要实现以下接口

//需要实现以下接口
class CPL_DLL VSIFilesystemHandler {virtual VSIVirtualHandle *Open( const char *pszFilename,const char *pszAccess,bool bSetError,CSLConstList papszOptions ) = 0;virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags) = 0;
}

VSIVirtualHandle需要是实现以下接口

class CPL_DLL VSIVirtualHandle {public:virtual int       Seek( vsi_l_offset nOffset, int nWhence ) = 0;virtual vsi_l_offset Tell() = 0;virtual size_t    Read( void *pBuffer, size_t nSize, size_t nCount ) = 0;virtual size_t    Write( const void *pBuffer, size_t nSize,size_t nCount)=0;virtual int       Eof() = 0;virtual int       Close() = 0;
}

最后在打开数据之前还需要注册一下:

VSIFileManager::InstallHandler(file.FullPath().c_str(), new cpl::GsVSIFilesystemHandler(file.FullPath().c_str(), pGDB));
m_pDS = (GDALDataset *)GDALOpen(file.FullPath().c_str(), GA_ReadOnly);

本文实现远程ftp文件访问并用GDAL解析, 具体代码如下:

#include "pch.h"
#include "vsifileimp.h"using namespace GeoStar::Kernel;
using namespace GeoStar::Utility;//FTP 实现的坑, FTP同一文件一个流没读完,下一个流不起作用, (IMG文件gdal内部需要打开和关闭两次)
//FTP  文件流不支持seek ,只能下载向前读, 这在tif文件得时候是可以得, 但是在img不行,
//FTP  不要视图多线程, 因为只能打开一个文件流,
//FTP  镶嵌数据集支持ftp是个玩具,需要上对象化存储int cpl::GsVSIVirtualHandle::Eof()
{return beof;
}
//return 0 on success or -1 one failure.
int cpl::GsVSIVirtualHandle::Seek(vsi_l_offset nOffset, int nWhence)
{if (nOffset < 0 || nOffset > filesize)return -1;if (nWhence == SEEK_SET){curOffset = nOffset;}else if (nWhence == SEEK_CUR){curOffset = curOffset + nOffset;}else{curOffset = filesize + nOffset;}beof = false;return 0;
}
//*@return 0 on success or -1 on failure.
vsi_l_offset cpl::GsVSIVirtualHandle::Tell()
{return curOffset;
}
//
//size_t cpl::GsVSIVirtualHandle::Read(void * pBufferIn, size_t nSize, size_t nCount)
//{
//  if (0 == nSize * nCount)
//      return 0;
//  unsigned char*pbufferhead = (unsigned char*)pBufferIn;
//  unsigned long long needsize = nCount * nSize;
//
//  if (needsize + curOffset <= loadsize)
//  {
//      GsInputStreamPtr read = m_TmpFile->OpenRead();
//      read->Seek(curOffset, GsStreamSeekOrigin::eSet);
//      int n = read->RawRead((unsigned char*)pbufferhead, needsize);
//      curOffset += n;
//      return n;
//  }
//  unsigned long long AllReturnSize = 0;
//  long long Infilesize = loadsize - curOffset;
//  if (Infilesize > 0)
//  {
//      GsInputStreamPtr read = m_TmpFile->OpenRead();
//      int tmpfileread  = read->RawRead((unsigned char*)pbufferhead, needsize);
//      pbufferhead += tmpfileread;
//      needsize -= tmpfileread;
//      curOffset += tmpfileread;
//      AllReturnSize += tmpfileread;
//  }
//  unsigned long long outfilesize = fabs(Infilesize);
//  unsigned long long needdownsize = outfilesize + needsize;
//  int buffsize = 1024;
//  GsGrowByteBuffer buff;
//  buff.Allocate(buffsize);
//  {auto write = m_TmpFile->OpenWrite();
//  unsigned long long downCount = 0;
//  //直接放文件
//  if (outfilesize < buffsize)
//      buffsize = outfilesize;
//  while (outfilesize > 0)
//  {
//      int n = this->FTPRead(buff.BufferHead(), 1, buffsize);
//      if (n <= 0)
//          break;
//      downCount += n;
//      outfilesize -= n;
//      if (outfilesize < buffsize)
//          buffsize = outfilesize;
//      loadsize += n;
//      buff.Allocate(n);
//      write->WriteBuffer(&buff);
//  }
//
//  buffsize = 1024;
//  int tmpwritecount = 0;
//  if (needsize < buffsize)
//      buffsize = needsize;
//  while (needsize > 0)
//  {
//      int n = this->FTPRead(pbufferhead, 1, buffsize);
//      if (n <= 0)
//          break;
//
//      buff.Allocate(n);
//      buff.Copy(pbufferhead, n);
//      tmpwritecount += write->WriteBuffer(&buff);
//      pbufferhead += n;
//      needsize -= n;
//      AllReturnSize += n;
//      curOffset += n;
//      loadsize += n;
//      if (needsize < buffsize)
//          buffsize = needsize;
//  }
//  write->Flush();
//  write->Close();
//  }
//  //curOffset += AllReturnSize;
//  return AllReturnSize;
//
//}
//#define BLOCKSIZE 1024*16
//size_t cpl::GsVSIVirtualHandle::Read(void * pBufferIn, size_t nSize, size_t nCount)
//{
//  if (0 == nSize * nCount)
//      return 0;
//  unsigned char*pbufferhead = (unsigned char*)pBufferIn;
//  long long needsize = nCount * nSize;
//
//  if (needsize + curOffset <= loadsize)
//  {
//      FILE* file = fopen(m_tmpFilePath.c_str(), "r");
//      fseek(file, curOffset, 0);
//      int n = fread((unsigned char*)pbufferhead, nSize, nCount, file);
//      curOffset += n;
//      fclose(file);
//      return n;
//  }
//  long long AllReturnSize = 0;
//  long long Infilesize = loadsize - curOffset;
//  if (Infilesize > 0)
//  {
//      FILE* file = fopen(m_tmpFilePath.c_str(), "r");
//      fseek(file, curOffset, 0);
//      int tmpfileread = fread((unsigned char*)pbufferhead, 1, needsize, file);
//      fclose(file);
//      pbufferhead += tmpfileread;
//      needsize -= tmpfileread;
//      curOffset += tmpfileread;
//      AllReturnSize += tmpfileread;
//  }
//  long long outfilesize = fabs(Infilesize);
//  long long needdownsize = outfilesize + needsize;
//  int buffsize = BLOCKSIZE;
//  GsGrowByteBuffer buff;
//  int tmp = 0;
//  buff.Allocate(buffsize);
//  {
//      FILE* file = fopen(m_tmpFilePath.c_str(), "a+");
//      long long downCount = 0;
//      //直接放文件
//      //if (outfilesize < buffsize)
//      //buffsize = outfilesize;
//      while (outfilesize > 0)
//      {
//          int n = this->FTPRead(buff.BufferHead(), 1, buffsize);
//          if (n <= 0)
//              break;
//
//          if (outfilesize < n)
//          {
//              buff.Allocate(outfilesize);
//          }
//          else
//          {
//              buff.Allocate(n);
//          }
//          tmp = fwrite(buff.BufferHead(), 1, buff.BufferSize(), file);
//          downCount += n;
//          outfilesize -= n;
//          loadsize += n;
//
//      }
//
//      buffsize = BLOCKSIZE;
//      int tmpwritecount = 0;
//      buff.Allocate(buffsize);
//      //if (needsize < buffsize)
//      //  buffsize = needsize;
//      while (needsize > 0)
//      {
//          int n = this->FTPRead(buff.BufferHead(), 1, buffsize);
//          if (n <= 0)
//              break;
//
//          buff.Allocate(n);
//          tmpwritecount += fwrite(buff.BufferHead(), 1, buff.BufferSize(), file);
//
//          if (needsize < n)
//          {
//              buffsize = needsize;
//              memcpy(pbufferhead, buff.BufferHead(), needsize);
//              //pbufferhead += n;
//              //needsize -= n;
//              AllReturnSize += needsize;
//              curOffset += needsize;
//              loadsize += n;
//          }
//          else
//          {
//              memcpy(pbufferhead, buff.BufferHead(), n);
//              pbufferhead += n;
//              needsize -= n;
//              AllReturnSize += n;
//              curOffset += n;
//              loadsize += n;
//          }
//
//
//      }
//      fflush(file);
//      fclose(file);
//  }
//
//  return AllReturnSize;
//
//}#define BLOCKSIZE 1024
#define BLOCKSIZE_C 1024
#define BLOCKSIZE_RC BLOCKSIZE*BLOCKSIZE * BLOCKSIZE_C
//分段读取目前是不成功,  在img文件的ftp文件中, 这里不停得打开关闭文件存在问题
size_t cpl::GsVSIVirtualHandle::Read2(void * pBufferIn, size_t nSize, size_t nCount)
{if (0 == nSize * nCount)return 0;unsigned char*pbufferhead = (unsigned char*)pBufferIn;unsigned long long needsize = nCount * nSize;if (needsize + curOffset > filesize)return 0;if (needsize + curOffset <= loadsize){FILE* file = fopen(m_tmpFilePath.c_str(), "rb");fseek(file, curOffset, 0);int n = fread((unsigned char*)pbufferhead, nSize, nCount, file);curOffset += n;fclose(file);return n;}unsigned long long AllReturnSize = 0;long long Infilesize = (loadsize > curOffset) ? (loadsize - curOffset) : (-1 * (curOffset - loadsize));if (Infilesize > 0){FILE* file = fopen(m_tmpFilePath.c_str(), "rb");fseek(file, curOffset, 0);int tmpfileread = fread((unsigned char*)pbufferhead, 1, needsize, file);fclose(file);pbufferhead += tmpfileread;needsize -= tmpfileread;curOffset += tmpfileread;AllReturnSize += tmpfileread;}unsigned long long outfilesize = fabs(Infilesize);unsigned long long needdownsize = outfilesize + needsize;int buffsize = BLOCKSIZE;GsGrowByteBuffer buff;int tmp = 0;buff.Allocate(buffsize);{FILE* file = fopen(m_tmpFilePath.c_str(), "ab+");unsigned long long downCount = 0;//直接放文件if (outfilesize < buffsize)buffsize = outfilesize;while (outfilesize > 0){int n = this->FTPRead(buff.BufferHead(), 1, buffsize);if (n <= 0)break;downCount += n;outfilesize -= n;loadsize += n;if (outfilesize < n)buffsize = outfilesize;buff.Allocate(n);tmp = fwrite(buff.BufferHead(), 1, buff.BufferSize(), file);}buffsize = BLOCKSIZE;int tmpwritecount = 0;buff.Allocate(buffsize);if (needsize < buffsize)buffsize = needsize;while (needsize > 0){int n = this->FTPRead(pbufferhead, 1, buffsize);if (n <= 0)break;needsize -= n;AllReturnSize += n;curOffset += n;loadsize += n;buff.Allocate(n);buff.Copy(pbufferhead, n);tmpwritecount += fwrite(buff.BufferHead(), 1, buff.BufferSize(), file);if (needsize < n)buffsize = needsize;pbufferhead += n;}fflush(file);fclose(file);}return AllReturnSize < 0 ? -1 : AllReturnSize;
}
size_t cpl::GsVSIVirtualHandle::ReadLocal(void * pBufferIn, size_t nSize, size_t nCount)
{if (0 == nSize * nCount)return 0;unsigned char*pbufferhead = (unsigned char*)pBufferIn;unsigned long long needsize = nCount * nSize;if (needsize + curOffset <= loadsize){//if (!rfile)FILE*  rfile = fopen(m_tmpFilePath.c_str(), "rb");int f = fseek(rfile, curOffset, 0);int n = fread((unsigned char*)pbufferhead, nSize, nCount, rfile);curOffset += n * nSize;//防止句柄耗尽,及时关闭fclose(rfile);return n;}return 0;
}
size_t cpl::GsVSIVirtualHandle::Read2Local(void * pBuffer, size_t nSize, size_t nCount)
{unsigned long long needsize = nCount * nSize;{GsGrowByteBuffer buff;long long tmpwritecount = 0;buff.Allocate(BLOCKSIZE);//if (!wfile)FILE*  wfile = fopen(m_tmpFilePath.c_str(), "ab+");long long needDownsize = (long long)curOffset - (long long)loadsize + (long long)needsize;if (filesize < BLOCKSIZE_RC)needDownsize = filesize;else if (filesize > BLOCKSIZE_RC){if (needDownsize < BLOCKSIZE_RC)needDownsize = BLOCKSIZE_RC;//if (needDownsize + loadsize > filesize)//{// needDownsize = (long long) filesize - (long long)loadsize;//}}while (needDownsize > 0){buff.Allocate(BLOCKSIZE);int n = this->FTPRead(buff.BufferHead(), 1, BLOCKSIZE);if (n <= 0)break;loadsize += n;buff.Allocate(n);needDownsize -= n;tmpwritecount += fwrite(buff.BufferHead(), 1, buff.BufferSize(), wfile);}fflush(wfile);防止句柄耗尽,及时关闭fclose(wfile);return tmpwritecount;}
}
size_t cpl::GsVSIVirtualHandle::Read(void * pBufferIn, size_t nSize, size_t nCount)
{unsigned long long needsize = nCount * nSize;if (filesize >0  && needsize + curOffset > filesize)return 0;int n = ReadLocal(pBufferIn, nSize, nCount);if (n > 0)return n;size_t writecount = Read2Local(pBufferIn, nSize, nCount);return  ReadLocal(pBufferIn, nSize, nCount);
}
cpl::GsVSIVirtualHandle::GsVSIVirtualHandle(GeoStar::Utility::GsVirtualFile * file)
{m_File = file;GsString tmpFile = GsFileSystem::TemporaryFolder();m_tmpFilePath = GsFileSystem::Combine(tmpFile.c_str(), GsMath::NewGUID().c_str());filesize = m_File->Size();
}cpl::GsVSIVirtualHandle::~GsVSIVirtualHandle()
{if (m_File){GsFile::Delete(m_tmpFilePath.c_str());m_File = NULL;}}size_t cpl::GsVSIVirtualHandle::FTPRead(void * pBufferIn, size_t nSize, size_t nCount)
{if (!m_ReadHandle)m_ReadHandle = m_File->OpenRead();if (!m_ReadHandle)return 0;long long nRawCount = nSize * nCount;if (0 == nRawCount)return 0;int r = m_ReadHandle->RawRead((unsigned char*)pBufferIn, nRawCount);//int retrycount = 3;//for (int i = 0; i < retrycount; i++)//{// if (r != 0)//      return r;// m_ReadHandle = m_File->OpenRead();//    if (!m_ReadHandle)//        return 0;// long long nRawCount = nSize * nCount;//    if (0 == nRawCount)//     return 0;// r = m_ReadHandle->RawRead((unsigned char*)pBufferIn, nRawCount);//}return r;
}size_t cpl::GsVSIVirtualHandle::Write(const void * pBuffer, size_t nSize, size_t nCount)
{return 0;
}
//return 0 on success or -1 on failure.
int cpl::GsVSIVirtualHandle::Close()
{防止句柄耗尽,及时关闭//fclose(rfile);//fclose(wfile);return 0;
}int cpl::GsVSIVirtualHandle::ReadMultiRange(int nRanges, void ** ppData,const vsi_l_offset* panOffsets,const size_t* panSizes)
{int nRet = 0;const vsi_l_offset nCurOffset = Tell();for (int i = 0; i < nRanges; i++){if (Seek(panOffsets[i], SEEK_SET) < 0){nRet = -1;break;}const size_t nRead = Read(ppData[i], 1, panSizes[i]);if (panSizes[i] != nRead){nRet = -1;break;}}Seek(nCurOffset, SEEK_SET);return nRet;
}cpl::GsVSIFilesystemHandler::GsVSIFilesystemHandler()
{
}cpl::GsVSIFilesystemHandler::GsVSIFilesystemHandler(GsVirtualFolder * foler)
{m_Root = foler;
}
cpl::GsVSIFilesystemHandler::GsVSIFilesystemHandler(const KERNEL_NAME::GsConnectProperty & conn, const UTILITY_NAME::GsConfig & conf)
{Init(conn, conf);
}
cpl::GsVSIFilesystemHandler::GsVSIFilesystemHandler(const char * file, KERNEL_NAME::GsGeoDatabase * pGdb)
{Init(file, pGdb);
}
GsString OpenType(const GsConnectProperty& conn, const GsConfig &conf)
{auto strVec = GsStringHelp::Split(conn.Server, ":");if (strVec.size() <= 0)return "Local";if (0 == GsStringHelp::CompareNoCase("Local", strVec[0])){return "Local";}else if (0 == GsStringHelp::CompareNoCase("FTP", strVec[0])){return "FTP";}else if (0 == GsStringHelp::CompareNoCase("WebDAV", strVec[0])){return "WebDAV";}else if (0 == GsStringHelp::CompareNoCase("OwnCloud", strVec[0])){return"OwnCloud";}else if (0 == GsStringHelp::CompareNoCase("NFS", strVec[0])){return"NFS";}else{return "Local";}
}
KERNEL_NAME::GsFileSystemClassPtr GetFS(const GsConnectProperty& conn, GsConfig &conf)
{UTILITY_NAME::GsObjectInstancerPtr ptrInstancer = UTILITY_NAME::GsClassFactory::CreateInstanceT<UTILITY_NAME::GsObjectInstancer>("FileSystemDataSourceFactory");if (!ptrInstancer){GS_W << "can't instance FileDataRoomCatalog ,need load gsspecialdatasource library first";return 0;}if (ptrInstancer->Exists("Server"))ptrInstancer->PropertyRef<UTILITY_NAME::GsString>("Server") = conn.Server;if (ptrInstancer->Exists("Database"))ptrInstancer->PropertyRef<UTILITY_NAME::GsString>("Database") = conn.Database;if (ptrInstancer->Exists("Password"))ptrInstancer->PropertyRef<UTILITY_NAME::GsString>("Password") = conn.Password;if (ptrInstancer->Exists("Port"))ptrInstancer->PropertyRef<int>("Port") = conn.Port;if (ptrInstancer->Exists("User"))ptrInstancer->PropertyRef<UTILITY_NAME::GsString>("User") = conn.User;if (ptrInstancer->Exists("Version"))ptrInstancer->PropertyRef<int>("Version") = conn.Version;if (ptrInstancer->Exists("Config"))ptrInstancer->PropertyRef<UTILITY_NAME::GsConfig>("Config") = conf;conf.Child("OpenType").Value(OpenType(conn, conf).c_str());return ptrInstancer->CreateInstanceT<KERNEL_NAME::GsFileSystemClass>();
}bool cpl::GsVSIFilesystemHandler::Init(const char*file, GsGeoDatabase* pGdb)
{GsConnectProperty conn = pGdb->ConnectProperty();m_Conf = pGdb->Config();m_Conn = conn;m_Conn.Server = file;m_ptrFsc = GetFS(m_Conn, m_Conf);if (m_ptrFsc)m_Root = m_ptrFsc->RootFolder();return !m_Root || !m_ptrFsc;
}
bool cpl::GsVSIFilesystemHandler::Init(const GsConnectProperty & conn, const GsConfig & conf)
{m_Conf = conf;m_Conn = conn;m_ptrFsc = GetFS(m_Conn, m_Conf);if (m_ptrFsc)m_Root = m_ptrFsc->RootFolder();return !m_Root || !m_ptrFsc;
}
GsString NonStandardUrlIP(const char * pszFilename) {GsString tmpstr = pszFilename;tmpstr = GsStringHelp::Replace(tmpstr.c_str(), "\\\\", "//");tmpstr = GsStringHelp::Replace(tmpstr.c_str(), "\\", "/");if (tmpstr.find("//") != tmpstr.npos){tmpstr = GsStringHelp::Replace(tmpstr.c_str(), "//", "/");auto tmps = GsStringHelp::Split(tmpstr.c_str(), "/");if (tmps.size() >= 2){tmpstr = tmps[1];}}return tmpstr;
}GsString NonStandardUrlBody(const char * pszFilename)
{GsString tmpstr = pszFilename;tmpstr = GsStringHelp::Replace(tmpstr.c_str(), "\\\\", "//");tmpstr = GsStringHelp::Replace(tmpstr.c_str(), "\\", "/");try{if (tmpstr.find("//") == tmpstr.npos)return tmpstr;if (tmpstr.size() > 6) {GsString mpstr = tmpstr.substr(6, tmpstr.size());auto st = mpstr.find("/");if (st != mpstr.npos){tmpstr = mpstr.substr(st + 1, mpstr.size());}}}catch (const std::exception & ex){GS_W << ex.what();}return tmpstr;
}VSIVirtualHandle * cpl::GsVSIFilesystemHandler::Open(const char * pszFilename, const char * pszAccess, bool bSetError, CSLConstList papszOptions)
{if (!m_Root)return 0;GsString strtmp = NonStandardUrlBody(pszFilename);auto file = m_Root->SubFile(strtmp.c_str());if (!file)return 0;return new GsVSIVirtualHandle(file);
}int cpl::GsVSIFilesystemHandler::Stat(const char * pszFilename, VSIStatBufL * pStatBuf, int nFlags)
{if (!m_Root)return -1;GsVirtualFileSystemPtr ptrfg = m_Root;GsString strtmp = NonStandardUrlBody(pszFilename);GsVirtualFilePtr file = 0;file = m_Root->SubFile(strtmp.c_str());if (!file)return -1;GsAny nChunkSize = file->Attributes()->Attribute(GsVirtualFilesSystemAttributeType::eChunkSize);GsAny nFileID = file->Attributes()->Attribute(GsVirtualFilesSystemAttributeType::eFileID);GsAny nFileSize = file->Size(); //file->Attributes()->Attribute(GsVirtualFilesSystemAttributeType::eFileSize);pStatBuf->st_size = nFileSize.Empty() ? 0 : nFileSize.AsLongLong();//pStatBuf->st_dev = nFileSize.Empty() ? 0 : nFileSize.AsLongLong();return 0;
}//void VSIInstallCurlFileHandler(void)
//{
//  VSIFilesystemHandler* poHandler = new cpl::VSICurlFilesystemHandler;
//  VSIFileManager::InstallHandler("/vsicurl/", poHandler);
//  VSIFileManager::InstallHandler("/vsicurl?", poHandler);
//}
//
//void VSIInstallCurlStreamingFileHandler(void)
//{
//  VSIFileManager::InstallHandler("/vsicurl_streaming/",
//      new VSICurlStreamingFSHandler);
//}

最后得效果就是可以跟访问本地文件一样访问远程得tif和img文件, 其他格式没有尝试.

但是这里有个限制我这里用得是FTP协议,  无法实现seek接口,  只能将文件一段段下载下来, 然后可以操作,  如果有那种远程资源访问能支持向前和向后seek文件就能完美了,  我也不用支持缓存了.

GDAL VSI文件扩展(virtual_file_systems扩展)相关推荐

  1. 修改数据库文件为自动扩展以达到表空间自动扩展的目的

    转自:http://space.itpub.net/519536/viewspace-605541 表空间自动扩展 1.数据文件自动扩展的好处 1)不会出现因为没有剩余空间可以利用到数据无法写入 2) ...

  2. 开启php的文件上传扩展,linux中如何通过php.ini添加扩展?

    在编译安装的时候,我只通过了以下命令来安装,然后我想像windows中那样修改 php.ini 就开启了扩展 ./configure \ --enable-fpm \ --with-fpm-user= ...

  3. Python Cookbook(第3版)中文版:15.18 传递已打开的文件给C扩展

    15.18 传递已打开的文件给C扩展¶ 问题¶ 你在Python中有一个打开的文件对象,但是需要将它传给要使用这个文件的C扩展. 解决方案¶ 要将一个文件转换为一个整型的文件描述符,使用 PyFile ...

  4. crx文件里面的html文件,javascript – Chrome扩展程序:在crx文件中打开html,标签上没有图标...

    您好我正在开发一个简单的chrome扩展,它通过在扩展名的.crx目录中打开index.html来替换当前的默认新标签页. 目前,新的标签页已经使用新的index.html页面进行了修改,但是标签上没 ...

  5. Windows系统批量修改文件后缀名/扩展名

    查看文件   查看文件是否有扩展名,没有后缀名通过ctrl+E打开计算机,找到"工具"->"文件夹选项"->"查看",取消勾选& ...

  6. Linux的文件权限理解及文件种类与扩展名

    前言 Linux的环境为一个多人多任务环境,因此出于各个用户之间的保密性原因,它的文件管理权限就显得十分重要. Linux一般将文件可读写身份分为三种类别,分别为: 拥有者(owner) 所属群组(g ...

  7. 计算机如何把文件设为隐藏,已知文件类型的扩展名如何设置显示与隐藏?

    当你想把文件扩展名隐藏或是显示的时候,有木有突然感觉有那么一瞬间皱着眉头过呢?当你想要设置显示与隐藏扩展名的时候却莫名其妙的发现"隐藏已知文件类型的扩展名"这一项选不见了,心理莫名 ...

  8. windows服务器设置文件属性设置去掉隐藏已知文件类型的扩展名(即文件后缀名可见)

    摘要: 1.文件后缀名不可见,系统运维过程容易发生同名不同后缀的文件操作混淆的情况 2.windows系统默认是文件后缀名不可见 3.所以需要更改一下配置. 4.操作步骤如下图: (1)点击组织-文件 ...

  9. 在VSCode中自定义文件类型和扩展名关联

    目录 标题 概述 实现步骤 总结 标题 在 VSCode 中自定义文件类型和扩展名关联 Customize file type and extension associations in VSCode ...

最新文章

  1. Postgresql:删除及查询字段中包含单引号的数据
  2. JavaScript中 for、for in、for of、forEach等使用总结
  3. JDK8的排序大法!!
  4. nginx html解析插件,nginx配置信息的解析流程
  5. pandas 菜鸟_再见Numpy,Pandas!又一个数据分析神器横空出现!
  6. Zabbix Server安装部署
  7. HFSS阵列天线设计与仿真1
  8. DoIP协议一致性测试
  9. edittext 内容长度
  10. iEx.ec——云计算业务的区块链革命
  11. 周记——20151214
  12. linux qemu的使用教程,详解QEMU网络配置的方法
  13. HDLBits—Exams/ece241 2014 q7a
  14. CSDN日报20170217——《辞职信:写给我的“藤野先生”》
  15. Android弹出关闭输入法
  16. tEST 1 for NOIP 2017.9.9.
  17. SPI与I2C总线协议
  18. Android 10 Firewall blacklist 设置范例
  19. 基于已有模型,训练新数据的方法
  20. 浅谈JVM的双亲委派机制

热门文章

  1. Appium Python API 中文版文档
  2. python不同时间周期k线_Python量化交易基础讲堂-股票分笔数据跨周期处理
  3. ssh税务管理系统web源码
  4. 电大2020计算机基础,2020年电大形考计算机基础答案(22页)-原创力文档
  5. 智慧社区信息管理系统的设计与实现(论文打包下载)
  6. 多家上市公司纷纷加强布局人工智能/智库2861
  7. Adobe发布Flash/HTML5转换工具:袋鼠
  8. 80前的前辈,你们都做了些什么?!(四)
  9. docker安装gamit_科学网—Ubuntu18.04 安装gamit10.7安装 - 陈超的博文
  10. 远距离遥控智能驱鸟器